Mockito入门和使用场景探究

本文详细介绍了Mockito,一个流行的Java测试框架,它通过模拟对象、依赖注入、验证行为等功能简化单元测试。文章涵盖了Mockito的主要用法,如创建模拟对象、部分模拟(spy)、静态方法模拟以及构造方法模拟,展示了其在各种测试场景中的应用。
摘要由CSDN通过智能技术生成

背景

在这里插入图片描述

Mockito是一个流行的Java测试框架,它通过提供简洁的API来帮助开发者编写单元测试。以下是Mockito的主要特点和用法:

  • 创建模拟对象:使用Mockito可以轻松地创建模拟对象,这些对象可以模拟真实对象的行为,用于替代真实对象的依赖项,以便进行独立的单元测试。

  • 部分模拟对象:Mockito还允许创建部分模拟对象,即spy对象。Spy对象保留了真实对象的部分行为,同时可以模拟方法的返回值。

  • 依赖注入:Mockito提供了@InjectMocks注解,用于自动注入模拟对象到待测试的类中,简化了测试代码的编写过程。

  • 验证行为:Mockito提供了丰富的方法来验证对象的行为,确保在测试过程中对象的方法被正确地调用。

  • 降低耦合度:通过使用Mockito,可以虚拟出外部依赖,降低测试组件之间的耦合度,使测试更加专注于代码的流程与结果。

  • 创建方式:Mockito提供了多种创建模拟对象的方式,包括使用Mockito.mock()方法或@Mock注解。这两种方式都可以有效地创建所需的模拟对象。

总的来说,Mockito通过提供强大的功能和方法,极大地简化了Java项目中单元测试的编写,使得开发者能够更加高效地进行测试驱动的开发。

使用场景

Mockito的使用场景包括但不限于以下几点:

  • 单元测试:在单元测试中,Mockito可以用来模拟复杂的依赖关系,确保测试的独立性和可靠性。通过模拟依赖对象的行为,可以专注于测试目标类的逻辑,而不受外部因素影响。
    集成测试:在集成测试中,Mockito可以用来模拟外部系统或服务的行为,这样可以在不实际调用外部系统的情况下验证系统的集成逻辑。

  • 系统测试:在系统测试中,Mockito可以用来模拟用户行为或特定的系统事件,以便在控制的环境下测试系统的整体行为。

  • 团队并行开发:当前后端或不同后端服务之间需要并行开发时,Mockito可以帮助开发者通过模拟接口来独立工作,从而加快开发进度并减少等待时间。

  • 测试驱动开发(TDD):在TDD实践中,开发人员在编写实际代码之前先编写测试用例。有了Mockito,即使某些功能尚未实现,也可以提前创建测试用例,因为可以模拟尚未完成的部分。

  • 隔离系统:当测试需要调用可能会对系统产生副作用的操作(如修改数据库)时,可以使用Mockito来创建一个虚拟的操作,避免对实际系统造成影响。
    模拟访问资源:如果需要测试的代码依赖于访问外部资源(如网络请求),使用Mockito可以模拟这些资源,避免因外部因素导致的测试不稳定。

  • 提高测试覆盖度:对于一些难以触发的场景(如服务器错误),可以使用Mockito来模拟这些情况,以确保测试用例的全面覆盖。

使用示例

@Mock注解

  • 最小化重复的模拟创建代码。
  • 使测试类更具可读性。
  • 使验证错误更容易读取,因为字段名称用于标识mock。
public class ArticleManagerTest {

       @Mock private ArticleCalculator calculator;
       @Mock private ArticleDatabase database;
       @Mock private UserProvider userProvider;

       private ArticleManager manager;

       @org.junit.jupiter.api.Test
       void testSomethingInJunit5(@Mock ArticleDatabase database) {

带有回调的存根

允许使用通用Answer接口进行存根处理。这里有一个示例:thenReturn()thenThrow()

 when(mock.someMethod(anyString())).thenAnswer(
     new Answer() {
         public Object answer(InvocationOnMock invocation) {
             Object[] args = invocation.getArguments();
             Object mock = invocation.getMock();
             return "called with arguments: " + Arrays.toString(args);
         }
 });

 //Following prints "called with arguments: [foo]"
 System.out.println(mock.someMethod("foo"));

方法返回结果

对于任何方法,都可以使用doThrow(), doAnswer(), doNothing(), doReturn() 和doCallRealMethod()来代替带有when()的相应调用。

 doThrow(new RuntimeException()).when(mockedList).clear();

   //following throws RuntimeException:
   mockedList.clear();
 

spy

Mockito中的spy对象是一种对真实对象进行部分模拟的方式,它允许在不改变原有类行为的基础上,对特定方法进行监控和验证。

使用spy对象的目的是为了在不完全模拟一个对象的同时,能够对某些特定的行为进行监控或者验证。以下是spy对象与mock对象的区别:

  • 默认行为:对于未指定的方法,spy对象会调用真实的方法并返回真实的值,而mock对象则不执行任何操作,对于有返回值的方法,默认返回null。

  • 使用方式:在spy对象中,通常使用doReturn…when语句来指定特定方法的行为,这样可以确保真实的方法不被执行。而在mock对象中,使用when…thenReturn语句来定义方法的行为,这样私有方法不会被执行。

  • 覆盖率统计:当使用spy对象时,原有的方法仍然会被执行,因此可以统计到代码覆盖率。而shadow对象则无法被统计覆盖率,因为它完全替换了原有对象的行为。

  List list = new LinkedList();
   List spy = spy(list);

   //可以选择截取一些方法:
   when(spy.size()).thenReturn(100);

   //使用spy调用*real*方法
   spy.add("one");
   spy.add("two");

   //打印“一”-列表的第一个元素
   System.out.println(spy.get(0));

   //size()方法已被存根-已打印100
   System.out.println(spy.size());

   //可选,可以验证
   verify(spy).add("one");
   verify(spy).add("two");
 

模拟静态方法

当使用内联mock maker时,可以在当前线程和用户定义的范围内模拟静态方法调用。通过这种方式,Mockito确保并发和顺序运行的测试不会干扰。为了确保静态mock保持临时性,建议在try-with-resources构造中定义作用域。

 assertEquals("foo", Foo.method());
 try (MockedStatic mocked = mockStatic(Foo.class)) {
 mocked.when(Foo::method).thenReturn("bar");
 assertEquals("bar", Foo.method());
 mocked.verify(Foo::method);
 }
 assertEquals("foo", Foo.method());

模拟构造方法

由于模拟构造的定义范围,一旦释放范围,对象构造就会返回到其原始行为。要定义mock行为并验证方法调用,使用返回的MockedConstruction。

 assertEquals("foo", new Foo().method());
 try (MockedConstruction mocked = mockConstruction(Foo.class)) {
 Foo foo = new Foo();
 when(foo.method()).thenReturn("bar");
 assertEquals("bar", foo.method());
 verify(foo).method();
 }
 assertEquals("foo", new Foo().method());
  • 21
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吴代庄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值