Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java @Mock、@MockBean和Mockito.Mock()之间的区别_Java_Spring_Spring Boot_Junit_Mockito - Fatal编程技术网

Java @Mock、@MockBean和Mockito.Mock()之间的区别

Java @Mock、@MockBean和Mockito.Mock()之间的区别,java,spring,spring-boot,junit,mockito,Java,Spring,Spring Boot,Junit,Mockito,当创建测试和模拟依赖项时,这三种方法之间的区别是什么 @MockBean: @MockBean MyService myservice; @模拟: @Mock MyService myservice; Mockito.mock() 最后很容易解释。如果您只查看注释的Javadoc,您将看到不同之处: @Mock:(org.mockito.Mock) 将一个字段标记为模拟字段 允许速记模拟创建 最小化重复的模拟创建代码 使测试类更具可读性 使验证错误更易于读取,因为字段名用于标识模拟

当创建测试和模拟依赖项时,这三种方法之间的区别是什么

  • @MockBean:

    @MockBean
    MyService myservice;
    
  • @模拟:

    @Mock
    MyService myservice;
    
  • Mockito.mock()


  • 最后很容易解释。如果您只查看注释的Javadoc,您将看到不同之处:

    @Mock:(
    org.mockito.Mock

    将一个字段标记为模拟字段

    • 允许速记模拟创建
    • 最小化重复的模拟创建代码
    • 使测试类更具可读性
    • 使验证错误更易于读取,因为字段名用于标识模拟
    @MockBean:(
    org.springframework.boot.test.mock.mockito.MockBean

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

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

    当在字段上使用
    @MockBean
    并在应用程序上下文中注册时,mock也将被注入到字段中

    Mockito.mock()

    它只是一个
    @Mock
    的表示


    普通Mockito库

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

    来自Mockito库,功能相当
    它们允许模拟类或接口,并记录和验证其行为。

    注释的使用方式较短,因此更可取,而且通常更可取。


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

    @Before 
    public void initMocks() {
        MockitoAnnotations.initMocks(this);
    }
    
    启用Mockito注释的另一种方法是通过指定执行此任务的
    MockitoJUnitRunner
    以及其他有用的内容,用
    @RunWith
    注释测试类:

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

    Spring启动库包装Mockito库

    import org.mockito.Mock;
    ...
    @Mock
    MyService myservice;
    
    这确实是一个:

    该类包含在
    弹簧启动测试
    库中。

    它允许在Spring中添加Mockito mock
    ApplicationContext

    如果上下文中存在与声明的类兼容的bean,它将用mock替换它。
    如果不是这样,它将在上下文中添加模拟作为bean

    Javadoc参考:

    可用于向弹簧添加模拟的注释 应用程序上下文

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


    何时使用经典/普通Mockito以及何时使用Spring Boot中的
    @MockBean

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

    因此,这里有一个简单的指导原则:

    当您编写一个不需要来自Spring引导容器的任何依赖项的测试时,经典/普通Mockito是一种可以遵循的方法:它速度快,并且有利于隔离测试组件。
    如果您的测试需要依赖Spring Boot容器,您还需要添加或模拟其中一个容器bean:
    @MockBean
    来自Spring Boot是一种方法


    Spring Boot的典型用法
    @MockBean

    import org.mockito.Mock;
    ...
    @Mock
    MyService myservice;
    
    当我们编写一个用
    @WebMvcTest
    (web测试片段)注释的测试类时

    很好地总结了这一点:

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

    别忘了@Mock需要手动调用MockitoRunner或initMocks。
    @MockBean
    @Mock
    之间唯一的区别是一个将Mock注入
    Spring应用程序上下文,而另一个则不会。@Doug您总结得很好,但需要记住MockBean是其中的一部分要使用
    @MockBean
    ,您需要使用
    @RunWith(SpringRunner.class)
    注释该类。但是,对于使用
    @Mock
    ,您可以使用
    @RunWith(MockitoJUnitRunner.class)
    并调用initMocks(),正如@Florian schaetz所提到的那样
    @Mock
    也可以使用SpringRunner,但是加载ApplicationContext会增加额外的开销。使用@MockBean创建bean的副本并将其注入ApplicationContext吗?或者模拟bean的所有方法都是null?如果所有方法都为null,我可以像使用@Mock一样对它们进行存根吗?如前所述,如果在Spring配置中已经定义了声明相同类型的bean,则使用
    @MockBean
    将替换应用程序上下文中的bean。注入是在声明
    @MockBean的类中执行的。
    DI机制的工作方式是:在DI上下文中注册一个对象,然后可以将Spring上下文中引用的对象注入到特定的类中。您不会在DI上下文中注入对象。
    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"));
        }
    
    }