前言
由于历史原因,@Mock 和 @MockBean 都会出现在项目代码里,这里记录下具体的区别。并突出 @MockBean 在 Spring Boot 中的使用时机
@Mock
来自于 Mockito 的包,本质上和以下代码没有区别。
MyService myservice = Mockito.mock(MyService.class);
@Mock 与 MockitoJUnitRunner 配合使用
如果发现 @Mock 不生效,可以检查一下 Runner 有没有配置正确
@RunWith(MockitoJUnitRunner.class)
@SpringBootTest(classes = MyService.class)
public class MyClassTest {
@Mock
MyService myService;
@Test
public void hello() {
Objects.requireNonNull(myService);
}
}
- 以上代码的等价写法:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MyClassTest.class)
public class MyClassTest {
@Mock
MyService myService;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
public void hello() {
Objects.requireNonNull(myService);
}
}
@MockBean
该注解来自于 spring-boot-test 的包。用于跟 Spring 容器集成。那什么时候需要跟 Spring 容器集成呢?回答这个问题就知道 @MockBean 的应用场景了。
@Mock 与 Spring Boot Test 配合使用
值得一提的是 Spring Boot Test 中 @WebMvcTest 是用于只测试 Spring MVC 功能的注解。这个注解的来由是 Junit 希望让测试变得轻量,不需要 Spring 加载所有的 bean 再执行测试。同样类型的注解还有 @JdbcTest 和 @DataMongoTest
@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"));
}
}
@MockBean 的使用时机
根据上述代码,可以理解 @MockBean 做了些什么:
// 把 Spring MVC 的bean 注入到容器中用于测试
@WebMvcTest(FooController.class)
public class FooControllerTest {
// 补充一个额外的bean用于支持测试
@MockBean
private FooService fooServiceMock;
}