创建测试和模拟依赖项时,这三种方法有什么区别?
@MockBean:
@MockBean
MyService myservice;
@Mock::
@Mock
Mockito.mock()
MyService myservice = Mockito.mock(MyService.class);
普通Mockito库
import org.mockito.Mock; ... @Mock MyService myservice;
和
import org.mockito.Mockito; ... MyService myservice = Mockito.mock(MyService.class);
来自Mockito库,功能等效。 它们允许模拟类或接口,并记录和验证其行为。
使用注释的方式更短,因此更可取,并且通常是更可取的。
请注意,要在测试执行期间启用Mockito批注, MockitoAnnotations.initMocks(this)必须调用静态方法。 为了避免测试之间的副作用,建议在每次测试执行之前先进行以下操作:
MockitoAnnotations.initMocks(this)
@Before public void initMocks() { MockitoAnnotations.initMocks(this); }
启用Mockito批注的另一种方法是@RunWith通过指定MockitoJUnitRunner执行此任务的,以及其他有用的东西来注释测试类:
@RunWith
MockitoJUnitRunner
@RunWith(org.mockito.runners.MockitoJUnitRunner.class) public MyClassTest{...}
Spring Boot库包装Mockito库
这确实是Spring Boot类:
import org.springframework.boot.test.mock.mockito.MockBean; ... @MockBean MyService myservice;
该类包含在spring-boot-test库中。
spring-boot-test
它允许在Spring中添加Mockito模拟ApplicationContext。 如果上下文中存在与声明的类兼容的bean,则将其 替换 为模拟。 如果不是的话,它 增加了 模拟的背景下,作为一个bean。
ApplicationContext
Javadoc参考:
可用于将模拟添加到Spring ApplicationContext的注释。 … 如果在上下文中定义的任何现有的相同类型的单个Bean将被模拟代替,如果没有定义现有的Bean,则将添加一个新的。
可用于将模拟添加到Spring ApplicationContext的注释。
…
如果在上下文中定义的任何现有的相同类型的单个Bean将被模拟代替,如果没有定义现有的Bean,则将添加一个新的。
什么时候使用经典/普通Mockito以及何时@MockBean从Spring Boot 使用?
单元测试旨在与其他组件隔离地测试组件,并且单元测试也有一个要求:执行时间要尽可能快,因为这些测试每天可能在开发人员计算机上执行数十次。
因此,这是一个简单的准则:
当您编写不需要从Spring Boot容器中获取任何依赖项的测试时,遵循经典/普通Mockito的方法是:它快速且有利于隔离测试组件。 如果您的测试需要依赖于Spring Boot容器, 并且 您还想添加或模拟其中一个容器bean:@MockBean从Spring Boot就是这样。
Spring Boot的典型用法@MockBean
当我们编写一个带有@WebMvcTest(Web测试片)注释的测试类时。
@WebMvcTest
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")); } }