Mockito.mock() vs @Mock vs @MockBean – Mockito.mock() vs @Mock vs @MockBean

最后修改: 2018年 7月 23日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this quick tutorial, we’ll look at three different ways of creating mock objects with Mockito and with the Spring mocking support. We’ll also discuss how they differ from each other.

在这个快速教程中,我们将看看用Mockito和Spring嘲讽支持创建嘲讽对象的三种不同方式。我们还将讨论它们之间有什么不同。

2. Mockito.mock()

2.Mockito.mock()

The Mockito.mock() method allows us to create a mock object of a class or an interface.

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

We can then use the mock to stub return values for its methods and verify if they were called.

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

Let’s look at an example:

我们来看看一个例子。

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

We don’t need to do anything else to this method before we can use it. We can use it to create mock class fields, as well as local mocks in a method.

在使用这个方法之前,我们不需要对它做任何其他处理。我们可以用它来创建模拟类字段,以及方法中的局部模拟。

3. Mockito’s @Mock Annotation

3.Mockito的@Mock注释

This annotation is a shorthand for the Mockito.mock() method. It’s important to note that we should only use it in a test class. Unlike the mock() method, we need to enable Mockito annotations to use this annotation.

这个注解是Mockito.mock()方法的一个缩写。值得注意的是,我们应该只在测试类中使用它。与mock()方法不同,我们需要启用Mockito注解来使用这个注解。

We can do this either by using the MockitoJUnitRunner to run the test, or by calling the MockitoAnnotations.initMocks() method explicitly.

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

Let’s look at an example using MockitoJUnitRunner:

让我们看看一个使用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();
    }
}

Apart from making the code more readable, @Mock makes it easier to find the problem mock in case of a failure, as the name of the field appears in the failure message:

除了使代码更具可读性外,@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)

Furthermore, when used in conjunction with @InjectMocks, it can reduce the amount of setup code significantly.

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

4. Spring Boot’s @MockBean Annotation

4.Spring Boot的@MockBean注解

We can use the @MockBean to add mock objects to the Spring application context. The mock will replace any existing bean of the same type in the application context.

我们可以使用@MockBean来将模拟对象添加到Spring应用上下文中。该模拟对象将取代应用上下文中任何现有的相同类型的Bean。

If no bean of the same type is defined, a new one will be added. This annotation is useful in integration tests where a particular bean, like an external service, needs to be mocked.

如果没有定义相同类型的Bean,将添加一个新的Bean。这个注解在集成测试中非常有用,因为在集成测试中需要模拟一个特定的Bean,比如一个外部服务。

To use this annotation, we have to use SpringRunner to run the test:

为了使用这个注解,我们必须使用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();
    }
}

When we use the annotation on a field, the mock will be injected into the field, as well as being registered in the application context.

当我们在一个字段上使用注解时,模拟将被注入到字段中,同时也被注册在应用程序上下文中。

This is evident in the code above. Here we used the injected UserRepository mock to stub the count method. Then we used the bean from the application context to verify that it is indeed the mocked bean.

这在上面的代码中很明显。在这里,我们使用注入的UserRepositorymock来存根countmethod.然后我们使用应用程序上下文的bean来验证它确实是被模拟的bean。

5. Conclusion

5.总结

In this article, we examined how the three methods for creating mock objects differ, and how we can use each of them.

在这篇文章中,我们研究了创建模拟对象的三种方法有何不同,以及我们如何使用它们中的每一种。

The source code that accompanies this article is available over on GitHub.

伴随着这篇文章的源代码可以在GitHub上找到