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

Dou*_*oug 106 java junit spring mockito spring-boot

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

  1. @MockBean:

    @MockBean
    MyService myservice;
    
    Run Code Online (Sandbox Code Playgroud)
  2. @嘲笑:

    @Mock
    MyService myservice;
    
    Run Code Online (Sandbox Code Playgroud)
  3. Mockito.mock()

    MyService myservice = Mockito.mock(MyService.class);
    
    Run Code Online (Sandbox Code Playgroud)

dav*_*xxx 153

普通Mockito图书馆

import org.mockito.Mock;
...
@Mock
MyService myservice;
Run Code Online (Sandbox Code Playgroud)

import org.mockito.Mockito;
...
MyService myservice = Mockito.mock(MyService.class);
Run Code Online (Sandbox Code Playgroud)

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

使用注释的方式较短,因此是优选的,通常是首选的.


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

@Before 
public void initMocks() {
    MockitoAnnotations.initMocks(this);
}
Run Code Online (Sandbox Code Playgroud)

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

@RunWith(org.mockito.runners.MockitoJUnitRunner.class)
public MyClassTest{...}
Run Code Online (Sandbox Code Playgroud)

包装Mockito库的Spring Boot库

这确实是一个Spring Boot类:

import org.springframework.boot.test.mock.mockito.MockBean;
...
@MockBean
MyService myservice;
Run Code Online (Sandbox Code Playgroud)

该课程包含在spring-boot-test图书馆中.

它允许在Spring中添加Mockito模拟ApplicationContext.
如果在上下文中存在与声明的类兼容的bean,则它将由mock 替换它.
如果不是这样,它会将上下文中的mock 添加为bean.

Javadoc参考:

可用于将模拟添加到Spring ApplicationContext的注释.

...

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


使用classic/plain Mockito时和使用@MockBeanSpring Boot时?

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

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

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


Spring Boot的典型用法 @MockBean

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

Spring Boot文档很好地总结了这一点:

通常@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"));
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 如上所述,如果在Spring配置中已经定义了声明相同类型的bean,那么使用`@MockBean`将替换应用程序上下文中的bean.注入是在声明`@MockBean的类中执行的.DI机制以这种方式工作:您在DI上下文中注册一个对象,然后您可以在特定的类中注入Spring上下文中引用的对象.您不在DI上下文中注入对象. (6认同)
  • 使用@MockBean会创建bean的副本并将其注入ApplicationContext吗?或者被模拟的bean的所有方法都是null?如果所有方法都为null,我可以像使用@Mock一样存根吗? (4认同)

Pat*_*ick 10

最后很容易解释.如果您只是查看注释的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.

  • 我们不要忘记@Mock需要手动调用MockitoRunner或initMocks. (5认同)
  • `@MockBean`和`@Mock`之间的唯一区别是,一个会将模拟注入`Spring ApplicationContext`而另一个不会? (4认同)
  • @Doug您总结得很好,但需要记住MockBean是Spring Boot的一部分 (3认同)