@ Mock,@ MovieBean和Mockito.mock()之间的区别

时间:2017-05-26 11:41:13

标签: java spring spring-boot junit mockito

在创建测试和模拟依赖项时,这三种方法之间有什么区别?

  1. @MockBean:

    @MockBean
    MyService myservice;
    
  2. @Mock:

    @Mock
    MyService myservice;
    
  3. Mockito.mock()

    MyService myservice = Mockito.mock(MyService.class);
    

2 个答案:

答案 0 :(得分:117)

普通Mockito图书馆

import org.mockito.Mock;
...
@Mock
MyService myservice;

import org.mockito.Mockito;
...
MyService myservice = Mockito.mock(MyService.class);

来自Mockito图书馆,功能相同。
它们允许模拟类或接口,并记录和验证行为。

使用注释的方式较短,因此更受欢迎,通常更受欢迎。

请注意,要在测试执行期间启用Mockito注释,请执行此操作 必须调用MockitoAnnotations.initMocks(this)静态方法 为避免测试之间的副作用,建议在每次测试执行之前执行此操作:

@Before 
public void initMocks() {
    MockitoAnnotations.initMocks(this);
}

启用Mockito注释的另一种方法是使用@RunWith通过指定执行此任务的MockitoJUnitRunner以及其他有用的东西来注释测试类:

@RunWith(org.mockito.runners.MockitoJUnitRunner.class)
public MyClassTest{...}

包装Mockito库的Spring Boot库

这确实是Spring Boot class

import org.springframework.boot.test.mock.mockito.MockBean;
...
@MockBean
MyService myservice;

该课程已包含在spring-boot-test资料库中。

它允许在Spring ApplicationContext中添加Mockito模拟 如果在上下文中存在与声明的类兼容的bean,则通过模拟替换。 如果不是这样,那么在上下文中添加作为bean。

Javadoc参考:

  

可用于向Spring添加模拟的注释   ApplicationContext中。

     

...

     

如果在上下文中定义了任何相同类型的现有单个bean   如果没有定义新的bean,则将被mock替换   将被添加。

使用classic / plain Mockito时和Spring Boot使用@MockBean时是什么?

单元测试旨在独立于其他组件测试组件,单元测试也有一个要求:在执行时间方面尽可能快,因为这些测试可能每天在开发人员计算机上执行十几次。 BR />

因此,这是一个简单的指导方针:

当您编写一个不需要Spring Boot容器的任何依赖项的测试时,经典/简单的Mockito是可以遵循的方式:它很快并且有利于隔离测试组件。
如果您的测试需要依赖Spring Boot容器,您还需要添加或模拟其中一个容器bean:Spring Boot中的@MockBean就是这样。

Spring Boot的典型用法@MockBean

当我们编写一个用@WebMvcTest注释的测试类(web测试切片)时。

The Spring Boot documentation总结得非常好:

  

@WebMvcTest通常仅限于一个控制器并在其中使用   与@MockBean组合以提供模拟实现   需要合作者。

以下是一个例子:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@RunWith(SpringRunner.class)
@WebMvcTest(FooController.class)
public class FooControllerTest {

    @Autowired
    private MockMvc mvc;

    @MockBean
    private FooService fooServiceMock;

    @Test
    public void testExample() throws Exception {
         Foo mockedFoo = new Foo("one", "two");

         Mockito.when(fooServiceMock.get(1))
                .thenReturn(mockedFoo);

         mvc.perform(get("foos/1")
            .accept(MediaType.TEXT_PLAIN))
            .andExpect(status().isOk())
            .andExpect(content().string("one two"));
    }

}

答案 1 :(得分:7)

最后很容易解释。如果您只是查看注释的javadoc,您将看到不同的内容:

@Mock:(org.mockito.Mock

  

将某个字段标记为模拟。

     
      
  • 允许速记模拟创建。
  •   
  • 最小化重复的模拟创建代码。
  •   
  • 使测试类更具可读性。
  •   
  • 使验证错误更易于阅读,因为字段名称用于标识模拟。
  •   

@MockBean :( org.springframework.boot.test.mock.mockito.MockBean

  

可用于将模拟添加到Spring ApplicationContext的注释。可以用作类级别注释,也可以用作@Configuration类中的字段,或者@RunWith SpringRunner的测试类。

     

可以按类型或bean名称注册模拟。在上下文中定义的任何现有的相同类型的单个bean将被mock替换,如果没有定义现有bean,则将添加新的bean。

     

当在字段上使用@MockBean时,以及在应用程序上下文中注册时,模拟也将被注入到字段中。

Mockito.mock()

  

它只是@Mock的表示。