💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
## Mockito简介 单元测试中如何减少对外部的依赖这正是 mockito 的使命,mockito 是一个流行的 mock 框架,可以与 junit 结合使用,mockito 允许我们创建和配置 mock 对象,使用 mockito 将大大简化了具有外部依赖项的类的测试开发。spring-boot-starter-test 中默认集成了 mockito,不需要额外引入。 ## Mockito使用 * 打桩:实际上就是对接口、类、方法、参数、返回值进行伪造或者模拟。 * ReflectionTestUtils * 注解的使用 * @Mock:真实对象的替代品 * @Spy:被测试对象需要一部分被执行、一部分被mock,需要用spy对目标对象进行包装 * thenReturn与doReturn差异 * 语法: * when-thenReturn * when(obj.method()).thenReturn(returnValue) * doReturn-when * doReturn(returnValue).when(obj).method() * 差异 | API | Mock Obj | Spy Obj | | --- | --- | --- | | when-thenReturn | × | ○ | | doReturn-when | × | × | ## maven依赖 ``` <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>xxx.yyy</version> <scope>test</scope> </dependency> ``` ## 注解介绍 * 在单元测试中使用@Mock, @Spy, @InjectMocks等注解时,需要进行初始化后才能使用 * 可以使用 @RunWith(MockitoJUnitRunner.class) 代替@RunWith(SpringRunner.class)进行初始化,也可以在测试类的构造方法中使用MockitoAnnotations.initMocks(this) 来初始化 * @Mock:创建mock对象,也可使用静态方法mock()创建 ~~~ List mockedList = mock(List.class); ~~~ * @Spy:和@Mock一样创建对象,区别在于@Spy会调用真实数据 * @InjectMocks:创建一个实例,其余用@Mock(或@Spy)注解创建的mock将被注入到用该实例中 ## Mockito的常用方法 | 方法名 | 描述 | | --- | --- | | Mockito.mock(classToMock) | 模拟对象 | | Mockito.verify(mock) | 验证行为是否发生 | | Mockito.when(methodCall).thenReturn(value1).thenReturn(value2) | 触发时第一次返回value1,第n次都返回value2 | | Mockito.doThrow(toBeThrown).when(mock).\[method\] | 模拟抛出异常。 | | Mockito.mock(classToMock,defaultAnswer) | 使用默认Answer模拟对象 | | Mockito.when(methodCall).thenReturn(value) | 参数匹配 | | Mockito.doReturn(toBeReturned).when(mock).\[method\] | 参数匹配(直接执行不判断) | | Mockito.when(methodCall).thenAnswer(answer)) | 预期回调接口生成期望值 | | Mockito.doAnswer(answer).when(methodCall).\[method\] | 预期回调接口生成期望值(直接执行不判断) | | Mockito.spy(Object) | 用spy监控真实对象,设置真实对象行为 | | Mockito.doNothing().when(mock).\[method\] | 不做任何返回 | | Mockito.doCallRealMethod().when(mock).\[method\] //等价于Mockito.when(mock.\[method\]).thenCallRealMethod(); | 调用真实的方法 | | reset(mock) | 重置mock | ## 例子 ``` import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.runners.MockitoJUnitRunner; import org.springframework.boot.test.context.SpringBootTest; import static org.mockito.Mockito.*; @RunWith(MockitoJUnitRunner.class) //@RunWith(SpringRunner.class) @SpringBootTest public class MockLoginTest { //对被测类中@Autowired的对象,用@Mock标注;对被测类自己,用@InjectMocks标注 @InjectMocks private UserServiceImpl userService; @Mock private UserRepository userDao; @Mock private BargainBlackListService bargainBlackListService; @Mock private DistributionUserService distributionUserService; @Mock private AuthorityService authorityService; @Before public void init(){ MockitoAnnotations.initMocks(this); } @Test public void loginTest() { //模拟方法动作 //spyUserService在调用getUserEntity方法的时候,指定返回事先定义好的userEntity UserService spyUserService = spy(userService); UserEntity userEntity = new UserEntity(); userEntity.setUserName("ppp"); doReturn(userEntity).when(spyUserService).getUserEntity(anyString()); when(bargainBlackListService.checkBlackList(anyString())).thenReturn(true); UserInfoDTO userInfoDTO = new UserInfoDTO(); userInfoDTO.setUserName("ppp"); userInfoDTO.setId("2c95808a644ade6801644ae37f730000"); spyUserService.updateUserInfo("0520b1d9-9806-4ec1-a095-dfcd8bea8fd6", userInfoDTO); } } ```