1. 概述

在这个快速教程中,我们将探讨使用Mockito和Spring模拟支持创建mock对象的三种方法,并讨论它们之间的差异。

2. Mockito.mock() 方法

Mockito.mock() 方法允许我们为一个类或接口创建mock对象。然后我们可以为它的方法设置返回值并验证是否被调用。

让我们看一个例子:

@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对象,也可以在方法中创建局部mock。

3. Mockito的 @Mock 注解

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

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

下面是一个使用MockitoJUnitRunner的例子:

@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使得在失败时找到问题mock更容易,因为字段名称会出现在失败信息中:

Wanted but not invoked:
mockRepository.count();
-> at org.baeldung.MockAnnotationTest.testMockAnnotation(MockAnnotationTest.java:22)
Actually, there were zero interactions with this mock.

  at org.baeldung.MockAnnotationTest.testMockAnnotation(MockAnnotationTest.java:22)

此外,当与@InjectMocks一起使用时,它可以显著减少设置代码量。

4. Spring Boot的 @MockBean 注解

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

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

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

@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();
    }
}

当我们在字段上使用注解时,mock将被注入到字段中,并注册到应用程序上下文中。

上述代码中可以看出这一点。我们使用注入的UserRepository mock来模拟count方法。然后我们使用应用程序上下文中的bean来验证它确实是mocked bean。

5. 总结

在这篇文章中,我们研究了创建mock对象的三种方法的差异以及如何使用它们。本文的源代码可在GitHub上获取。


« 上一篇: SqlResultSetMapping指南
» 下一篇: Java Weekly, 第239期