Mockito测试框架入门与使用

Mockito

Mockito 是一个流行的 Java 单元测试框架,用于模拟(mock)对象以便进行单元测试。它可以帮助开发人员创建和管理模拟对象,以便在测试过程中替换那些不容易构造或获取的对象,从而达到测试被测代码的行为,而无需依赖于实际的外部系统或服务。

Mockito 的主要特点包括:

  1. 模拟对象:Mockito 允许创建模拟对象,这些模拟对象具有与真实对象相似的行为,但实际上只是虚拟的对象实例。通过模拟对象,可以模拟外部依赖、交互行为等,从而使测试更加独立和可控。

  2. 验证行为:Mockito 提供了丰富的 API 来验证模拟对象的交互行为,例如方法是否被调用、调用次数、参数匹配等。通过验证行为,可以确保被测代码按预期执行了与外部系统的交互。

  3. Stubbing 方法:Mockito 允许对模拟对象的方法进行 Stubbing,即定义当调用某个方法时应该返回的值。这样可以模拟不同的场景和条件,以覆盖多种测试情况。

  4. 灵活性:Mockito 提供了简洁且易于使用的 API,支持与 JUnit、TestNG 等测试框架集成。同时,它还提供了丰富的功能和扩展,可以满足各种测试场景的需求。

Mockito使用

Mockito依赖

SpringBoot默认的Mock框架是Mockito,和junit一样,只需要依赖spring-boot-starter-test就可以了

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

如果是单独添加依赖,那么添加下面依赖

 	<dependency>
      <groupId>org.mockito</groupId>
      <artifactId>mockito-core</artifactId>
      <version>{mockito_version}</version>
    </dependency>
    <dependency>
      <groupId>org.mockito</groupId>
      <artifactId>mockito-junit-jupiter</artifactId>
      <version>{mockito_version}</version>
    </dependency>

mockito-core:Mockito 核心依赖,提供了 Mockito 框架的核心功能和 API。

mockito-junit-jupiter:Mockito 与 JUnit Jupiter 的集成依赖,用于在 JUnit 5 环境下使用 Mockito 进行单元测试。

如果需要使用内联Mocks,那么还需要添加下面这个依赖

mockito-inline:Mockito 的内联依赖,用于支持内联(inline)Mocks 的创建和使用。

Mockito常用注解

@RunWith

@RunWith注解用于在JUnit测试中指定运行器(Runner),常用的有以下两种

  1. @RunWith(MockitoJUnitRunner.class)
    • @RunWith(MockitoJUnitRunner.class) 是Mockito框架提供的JUnit运行器,用于运行使用Mockito进行单元测试的类。
    • 当使用 @RunWith(MockitoJUnitRunner.class) 注解一个测试类时,Mockito会自动初始化这个类中使用 @Mock@InjectMocks 等注解创建的模拟对象。
    • 这样可以简化测试类的设置过程,使得在测试中可以直接使用模拟对象而不需要手动初始化。
@RunWith(MockitoJUnitRunner.class)
public class SomeTestClass {
    @Mock
    private SomeService someService;

    // Test methods using mock objects
}
  1. @RunWith(SpringRunner.class)
    • @RunWith(SpringRunner.class) 是Spring Framework提供的JUnit运行器,用于运行基于Spring的集成测试。
    • 当使用 @RunWith(SpringRunner.class) 注解一个测试类时,Spring会加载应用程序上下文,并可以通过@Autowired等注解注入Spring管理的Bean。
    • 这样可以进行更真实的集成测试,包括与数据库、外部服务的交互等。
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringIntegrationTest {
    @Autowired
    private SomeService someService;

    // Integration test methods using Spring context
}

注:如果是在Spring Boot项目中,使用了@SpringBootTest注解,就不需要再额外使用@RunWith注解了。因为在Spring Boot中,@SpringBootTest注解用于创建一个完整的应用程序上下文,这样你就可以在测试中使用所有的Spring Beans和自动配置。这个注解本身就包含了@RunWith(SpringRunner.class)的功能,因此你不需要显式地添加@RunWith注解。

@Test
标记测试方法,被 @Test 注解标记的方法会被 JUnit 的运行器执行,作为测试方法进行测试。

@MockBean

模拟Spring Boot应用程序中Spring上下文的对象,@MockBean是Spring Boot测试框架的一部分(属于spring-boot-test包),@MockBean注解的类将替代Spring容器中同类型的类。如果同类型的类不存在,@MockBean会自动定义并添加它。对于不是bean的依赖,@MockBean会将它模拟成bean并与存在的依赖一起添加到上下文中。在Spring Boot的测试类中,@MockBean通常与@SpringBootTest和@AutoConfigureMockMvc等注解一起使用。

在Spring Boot的测试类中,通常更倾向于使用@MockBean来模拟对象,因为它与Spring Boot的测试框架有更好的集成。

@Mock

创建一个模拟对象,并注入到测试类中。通常和 @InjectMocks 注解一起使用,用于为测试类中的被测对象注入模拟对象。当你使用 @Mock 注解一个对象时,Mockito 会为你创建一个该对象的模拟实例。这个模拟实例的行为(即方法的返回值和它们被调用的方式)可以被精确地控制和验证。默认情况下,模拟对象上的所有方法调用都会返回 null(对于引用类型)或默认值(对于原始类型)。你可以使用 when(…).thenReturn(…)、when(…).thenThrow(…) 等 Mockito 方法来定义模拟对象的行为。

@Spy
用于创建一个部分模拟对象,与@Mock不同,@Spy创建的是一个实际对象的代理,并且允许你选择性地模拟对象中的某些方法。默认情况下,所有未被特别模拟的方法都会调用实际对象的方法,
通常与doReturn/doThrow等方法结合使用。

@Captor
用于捕获方法参数,以便验证方法调用参数是否正确。

@InjectMocks

注入被测对象,并自动将 @Mock 和 @Spy 标注的对象注入到被测对象中。

public class SomeTestClass {
    @Mock
    private SomeService someService;

    @InjectMocks
    private SomeController someController;

    
}

@Before 和 @After
JUnit 提供的注解,在每个测试方法执行之前和之后分别执行一段代码。通常用于设置测试的前置条件或进行资源的清理工作。

public class SomeTestClass {
    @Before
    public void setUp() {
        // Set up test data or initialize resources
    }

    @After
    public void tearDown() {
        // Clean up resources
    }

    @Test
    public void testSomeMethod() {
        // Test method
    }
}

Mockito常用方法

Mockito.when()

Mockito.when() 是 Mockito 框架中的一个方法,用于设置模拟对象的方法调用行为。它通常与 thenReturn()、thenThrow() 或 thenAnswer() 方法一起使用。

Mockito.when(mock.methodCall()).thenReturn(value) 的语法表示当模拟对象的 methodCall() 方法被调用时,应该返回指定的 value 值。

下面是 Mockito.when() 方法的一些常见用法:

  1. 返回固定值:

使用thenReturn返回一个固定值,如果返回多个值,使用逗号分隔

// 当 getUserById() 方法被调用时,返回一个预先定义的 User 对象
Mockito.when(userServiceMock.getUserById(1)).thenReturn(new User("Alice"));

// 第一次调用 getUserById() 返回 Alice,第二次调用返回 Bob
Mockito.when(userServiceMock.getUserById(1)).thenReturn(new User("Alice")).thenReturn(new User("Bob"));
  1. 抛出异常

使用thenThrow可以抛出一个指定的异常

Mockito.when(userServiceMock.saveUser(null)).thenThrow(new IllegalArgumentException("Invalid parameter"));
  1. 使用 Answer 接口自定义行为

使用thenAnswer方法,传入Answer接口的实现类,就可以实现自定义返回

// 根据输入参数计算结果并返回
Mockito.when(calculatorMock.calculate(Mockito.anyInt(), Mockito.anyInt())).thenAnswer(invocation -> {
    int a = invocation.getArgument(0);
    int b = invocation.getArgument(1);
    return a + b;
});

Mockito.mock(Class classToMock)

用于创建一个指定类的模拟对象

Mockito.doReturn()

Mockito.doReturn() 用于设置模拟对象方法的返回值。与 Mockito.when().thenReturn() 方法类似,Mockito.doReturn() 也用于模拟方法调用时的返回结果,但在某些特定情况下会更加灵活和有效。

以下是 Mockito.doReturn() 方法的一些常见用法:

  1. 设置模拟对象方法的返回值:
// 使用 doReturn() 设置 getUserById() 方法的返回值
Mockito.doReturn(new User("Alice")).when(userServiceMock).getUserById(1);
  1. 处理 void 方法的行为:
// 设置 delete() 方法为无返回值时的行为
Mockito.doNothing().when(userServiceMock).deleteUser(1);

// 设置 void 方法抛出异常时的行为
Mockito.doThrow(new RuntimeException("Unable to delete user")).when(userServiceMock).deleteUser(2);

Mockito.verify():

Mockito.verify() 用于验证模拟对象的方法是否被调用以及调用的次数。它通常与 times()、atLeastOnce()、never() 等方法一起使用。

Mockito.verify(mock, times(n)).methodCall() 的语法表示验证模拟对象的 methodCall() 方法被调用了 n 次。

以下是 Mockito.verify() 方法的一些常见用法:

  1. 验证方法是否被调用:

verify(mock): 验证模拟对象的方法至少被调用了一次。这是 verify 的默认行为。

Mockito.verify(userServiceMock).getUserById(1);
  1. 验证方法调用次数:

verify(mock, times(n)): 验证模拟对象的方法被调用了指定次数。

// 验证 getUserById() 方法被调用了两次
Mockito.verify(userServiceMock, times(2)).getUserById(1);

// 验证 saveUser() 方法至少被调用了一次
Mockito.verify(userServiceMock, atLeastOnce()).saveUser(Mockito.any(User.class));

// 验证 deleteUser() 方法从未被调用
Mockito.verify(userServiceMock, never()).deleteUser(2);

Mockito.any(Class type)

Mockito.any(Class type) 用于创建一个匹配任意指定类型的参数的匹配器。在设置模拟对象方法的行为时,我们经常会使用 Mockito.any() 来匹配任意参数。

下面是 Mockito.any() 方法的一些常见用法:

// 当 saveUser() 方法的参数为任意对象,都返回 true
Mockito.when(userServiceMock.saveUser(Mockito.any())).thenReturn(true);

// 当 saveUser() 方法的参数为任意 User 对象时,都返回 true
Mockito.when(userServiceMock.saveUser(Mockito.any(User.class))).thenReturn(true);


// 当 calculate() 方法的两个参数为任意整数时,返回固定值 10
Mockito.when(calculatorMock.calculate(Mockito.anyInt(), Mockit.anyInt())).thenReturn(10);

Mockito.reset
Mockito.reset(mock):重置模拟对象的状态,清除之前的交互和验证。

Mockito.reset(userServiceMock);

Mockito.eq()

Mockito.eq() 用于创建一个匹配特定参数值的匹配器。当你想在模拟对象的方法调用中匹配一个特定的参数时,你可以使用 eq。它通常与 when 和 verify 等方法一起使用。
下面是 Mockito.eq() 方法的一些常见用法:

  1. 匹配特定参数值:
// 当 getUserById() 方法的参数为 1 时返回特定的结果
Mockito.when(userServiceMock.getUserById(Mockito.eq(1))).thenReturn(new User("Alice"));

// 当 calculate() 方法的两个参数为特定整数时返回固定值 10
Mockito.when(calculatorMock.calculate(Mockito.eq(2), Mockito.eq(3))).thenReturn(10);
  1. 验证方法调用时特定参数值:
// 验证 deleteUser() 方法被调用时传入的参数为特定整数
Mockito.verify(userServiceMock).deleteUser(Mockito.eq(1));

在这个例子中,verify 方法会确保 userServiceMock.deleteUser方法被调用过,并且传递的参数是 1。如果没有这样的调用发生,或者传递了不同的参数,那么验证将会失败。

需要注意的是,eq 只能用于精确匹配。如果你想匹配任何参数(不关心实际值),你应该使用 any()。

  • 50
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Mockito 是一个基于 Java 的开源单元测试框架使用 Mockito 来进行单元测试可以让您更轻松地编写和运行测试,而无需实际依赖于所有可能的外部依赖项。 以下是一个简单的使用 Mockito 进行单元测试的步骤: 1.添加 Mockito 依赖项到您的 pom.xml 文件中。这可以通过下面的代码完成: <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>2.25.1</version> <scope>test</scope> </dependency> 2.创建一个包含一些需要测试的方法的 Java 类。 3.在测试类中创建一个 Mock 对象,并使用 Mockito.when() 方法模拟对象的行为。 4.使用 assertEquals() 断言来比较模拟的对象的预期结果与实际结果是否一致。 这里是一个使用 Mockito 进行单元测试的示例: public class CalculatorTest { @Mock private CalculatorService calculatorService; private Calculator calculator; @Before public void setUp(){ MockitoAnnotations.initMocks(this); calculator = new Calculator(calculatorService); } @Test public void testAdd(){ when(calculatorService.add(2,3)).thenReturn(5); assertEquals(10, calculator.perform(2,3)); } } 在这个示例中,我们模拟了一个 CalculatorService 对象,并在测试方法中调用了 calculator.perform(2,3) 方法。当我们调用 add() 方法时,它会返回 5,我们使用 assertEquals() 来确保实际结果等于预期结果。 注意:在上面的示例中,我们在 setUp() 方法中初始化了 Mockito,以确保 Mock 对象已正确注入。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值