Plain 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{...}
Spring Boot 库封装了 Mockito 库
这确实是Spring Boot class:
import org.springframework.boot.test.mock.mockito.MockBean;
...
@MockBean
MyService myservice;
该类包含在spring-boot-test 库中。
它允许在 Spring ApplicationContext 中添加 Mockito 模拟。
如果上下文中存在与声明的类兼容的 bean,它会将其替换为 mock。
如果不是这种情况,它将在上下文中添加模拟作为 bean。
Javadoc 参考:
可用于向 Spring 添加模拟的注解
应用程序上下文。
...
如果上下文中定义了任何现有的相同类型的单个 bean
将被模拟替换,如果没有现有的 bean 被定义一个新的
将被添加。
何时使用经典/纯 Mockito 以及何时使用 Spring Boot 中的 @MockBean?
单元测试旨在独立于其他组件来测试一个组件,并且单元测试还有一个要求:在执行时间方面尽可能快,因为这些测试可能每天在开发人员机器上执行数十次。
因此,这是一个简单的指南:
当您编写一个不需要来自 Spring Boot 容器的任何依赖项的测试时,经典/普通的 Mockito 是可以遵循的方法:它速度快并且有利于被测试组件的隔离。
如果您的测试需要依赖 Spring Boot 容器并且您还想添加或模拟容器 bean 之一:Spring Boot 中的@MockBean 就是这样。
Spring Boot的典型用法@MockBean
当我们编写一个用@WebMvcTest(网络测试切片)注释的测试类时。
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"));
}
}