Mockito的几种Mock方法

1. 概述

Mockito是一套简洁易用的 Mocking 框架,本文我们将介绍创建模拟对象的三种不同方式以及它们之间的区别 - 使用Mockito和Spring模拟支持。

2. Mockito.mock()

所述Mockito.mock()方法允许我们创建一个类或一个接口的一个模拟对象。

然后,我们可以使用mock来存储其方法的返回值,并验证它们是否被调用。

我们来看一个例子:

1
2
3
4
5
6
7
8
9
10
@Test
public void givenCountMethodMocked_WhenCountInvoked_ThenMockedValueReturned() {
UserRepository localMockRepository = Mockito.mock(UserRepository.class);
Mockito.when(localMockRepository.count()).thenReturn(111L);

long userCount = localMockRepository.count();

Assert.assertEquals(111L, userCount);
Mockito.verify(localMockRepository).count();
}

在使用之前,此方法不需要执行任何其他操作。我们可以使用它来创建 Mock 类字段以及方法。

3. Mockito的@Mock Annotation

此注释是Mockito.mock()方法的简写。同样,我们应该只在测试类中使用它。与mock()方法不同,我们需要启用Mockito注释才能使用此注释。

我们可以通过使用 MockitoJUnitRunner来运行测试或 显式调用 MockitoAnnotations.initMocks()方法来实现。

让我们看一个使用MockitoJUnitRunner的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@RunWith(MockitoJUnitRunner.class)
public class MockAnnotationUnitTest {

@Mock
UserRepository mockRepository;

@Test
public void givenCountMethodMocked_WhenCountInvoked_ThenMockValueReturned() {
Mockito.when(mockRepository.count()).thenReturn(123L);

long userCount = mockRepository.count();

Assert.assertEquals(123L, userCount);
Mockito.verify(mockRepository).count();
}
}

除了使代码更易读,@Mock在发生故障的情况下,它更容易找到故障的问题所在,因为它会将出现问题的字段名称显示在异常信息中

1
2
3
4
5
6
Wanted but not invoked:
mockRepository.count();
-> at com.doleje.MockAnnotationTest.testMockAnnotation(MockAnnotationTest.java:22)
Actually, there were zero interactions with this mock.

at com.doleje.MockAnnotationTest.testMockAnnotation(MockAnnotationTest.java:22)

此外,当与@InjectMocks结合使用时,它可以显着减少设置代码的数量。

4. Spring Boot的@MockBean注释

我们可以使用@MockBean将模拟对象添加到Spring应用程序上下文中。mock将替换应用程序上下文中任何相同类型的现有bean。

如果没有定义相同类型的bean,则会添加一个新bean。此注释在集成测试中很有用,在集成测试中需要模拟特定的bean(例如,外部服务)。

要使用此注解,我们必须使用SpringRunner来运行测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@RunWith(SpringRunner.class)
public class MockBeanAnnotationIntegrationTest {

@MockBean
UserRepository mockRepository;

@Autowired
ApplicationContext context;

@Test
public void givenCountMethodMocked_WhenCountInvoked_ThenMockValueReturned() {
Mockito.when(mockRepository.count()).thenReturn(123L);

UserRepository userRepoFromContext = context.getBean(UserRepository.class);
long userCount = userRepoFromContext.count();

Assert.assertEquals(123L, userCount);
Mockito.verify(mockRepository).count();
}
}

我们用 @MockBean 来 Mock 了一个 UserRepository 对象,并注入到 Spring 容器中,这样我们在后面的测试过程中就可以直接从 context 中获取这个 Mock Bean,同样也可以设置其 Mock 行为与返回数据。

5.结论

在本文中,我们看到了创建模拟对象的三种方法有何不同以及如何使用它们。