有些bean不想Mock,则必须要启动Spring容器,使用容器帮忙注入的Bean,需要进行Mock行为的类此时必须用MockBean注入。
在单元测试中,大多数都是用的Mock注入,因为Mock注入一般可以满足需求。但是一次测试中,应该属于集成测试,需要容器中相关的类,所以Mock注入不能满足要求,只能用MockBean注入。@mockBean注解将Mock对象添加到Spring上下文中。注解的对象将替换Spring上下文中任何相同类型的现有bean,如果没有定义相同类型的bean,将添加一个新的bean。
如果是简单的Mock,则配置非常简单,如下:

这里不需要借助任何容器。对于MockBean,是需要启动容器,配置如下:

上面是JUnit4的写法,JUnit5的更简单,只需要@SpringBootTest注解即可启动SpringBoot容器测试。
@SpringBootTest public class OrderServiceTest { @Resource private OrderService orderService; @Test public void testInsert() { Order order = new Order(); order.setOrderNo("A001"); order.setUserId(100); orderService.insert(order); } }
通过SpringRunner.class,和@SpringBootTest,配置运行环境为test启动Spring容器。通过@Autowired注入测试类UnitTestMockBean。
这里重点:UnitTestMockBean是通过容器注入的,UnitTestRepository是通过MockBean注入的。
下面图片的UnitTestEntityCheckService这个类就是 本文主题,这个类不想Mock,这个类用的是容器的。
UnitTestMockBean是通过容器注入,同时也会注入UnitTestEntityCheckService,但是UnitTestRepository是通过MockBean注入的。

代码可以自己看 github地址:MockBean的使用
package pers.xue.skills.service; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit4.SpringRunner; import pers.xue.skills.entity.UnitTestEntity; import pers.xue.skills.repository.UnitTestRepository; import java.util.Arrays; import java.util.List; /** * 注意: * 1、Mock不需要依赖Spring环境,MockBean是需要Spring容器支持,但是配置环境可以启动test.yml * MockBean场景: 可以进行一些简单的大部分的测试,但是如果有些类你不能Mock时,需要用容器生成的类,比如本例子中的 * UnitTestEntityCheckService,它是一个公共类,可以供很多地方使用,这个时候你需要借助容器中的它去实现,这个时候需要MockBean去Mock一些其它需要Mock的。 * 2、@RunWith(MockitoJUnitRunner.class) 不能用这个,这个是Mock环境的,不会加载Spring环境 * 3、启动Spring环境,可以用SpringBootTest、或者可以用Context * 4、用ActiveProfiles配置要用的配置类 * 5、初步测试是MockBean能注入Mock之后的值,说明启动了Spring环境,或者可以通过控制台看到-The following profiles are active: test * * @author :HUANG ZHI XUE * @date :Create in 2022-06-09 */ @RunWith(SpringRunner.class) @SpringBootTest @ActiveProfiles("test") public class UnitTestMockBeanTest { @MockBean UnitTestRepository unitTestRepository; @Autowired UnitTestMockBean unitTestMockBean; @Test public void testGetEligibleUnitTestEntity() { List<UnitTestEntity> unitTestEntities = Arrays.asList(new UnitTestEntity(1, "content")); Mockito.when(unitTestRepository.findAll()).thenReturn(unitTestEntities); List<UnitTestEntity> eligibleUnitTestEntity = unitTestMockBean.getEligibleUnitTestEntity(); Assert.assertEquals(unitTestEntities, eligibleUnitTestEntity); } }
总结:
如果测试中不需要用到容器中的东西,即所有都可以Mock注入,那Mock够用了,大部分也够…
如果测试中需要用到一部分不想Mock的类,比如Mapper,公共判断等的这些类,则可以启动Spring容器,那些不想要Mock的直接不管,让容器注入,那些想Mock此时不能用注解@Mock,只能用@MockBean。
归纳差异:前者不需要容器,比较简单,后者需要启动容器。