mockito加junit搞定单元测试-cnblog
转自:mockito加junit搞定单元测试
https://www.bilibili.com/video/BV1P14y1k7Hi?p=1&vd_source=a3ca5632ce12ee8045822c508dc81551
其他好文推荐:
1、2023单元测试利器Mockito框架详解(超详细~)
https://blog.csdn.net/m0_58026506/article/details/131423775
2、一文让你快速上手 Mockito 单元测试框架!https://zhuanlan.zhihu.com/p/386179879
3、【测试相关】Java Mock框架之Mockito https://www.jianshu.com/p/667bffb8b869
一、简介
二.mockito的单独使用
2.1 mock对象与spy对象
ps: 上面2.2表中表示junit5和4的初始化注解不一样地方,后面我们所讲的就以junit5来讲了。
2.2.1. Mockito与JUnit5的集成
参考:https://www.baeldung.com/mockito-junit-5-extension
除了Mockito本身的jar以及JUnit5本身的jar外,还需要依赖:mockito-junit-jupiter
,简单起见,可直接引入Spring Boot的test,它已经帮我们解决了依赖问题,并且天然的支持Mockito和JUnit5(需要Spring Boot 2.4.0+,否则支持的是JUnit4):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
或者使用如下依赖
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
2.2.2 代码演示:
方式一:通过@ExtendWith(MockitoExtension.class) + @Mock等注解
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
class MemberServiceImplTest {
@Mock
private MemberLevelDao mockMemberLevelDao;
@Spy
private MemberLevelDao spyMockMemberLevelDao;
@Test
void testMock1() {
// 判断某对象是不是mock对象 true
System.out.println("Mockito.mockingDetails(mockMemberLevelDao).isMock() = " + Mockito.mockingDetails(mockMemberLevelDao).isMock());
// false
System.out.println("Mockito.mockingDetails(mockMemberLevelDao).isSpy() = " + Mockito.mockingDetails(mockMemberLevelDao).isSpy());
// ture mock对象包含spy对象,spy对象的mock对象的一种特殊的情况
System.out.println("Mockito.mockingDetails(spyMockMemberLevelDao).isMock() = " + Mockito.mockingDetails(spyMockMemberLevelDao).isMock());
// true
System.out.println("Mockito.mockingDetails(spyMockMemberLevelDao).isSpy() = " + Mockito.mockingDetails(spyMockMemberLevelDao).isSpy());
}
}
打印结果:
Mockito.mockingDetails(mockMemberLevelDao).isMock() = true
Mockito.mockingDetails(mockMemberLevelDao).isSpy() = false
Mockito.mockingDetails(spyMockMemberLevelDao).isMock() = true
Mockito.mockingDetails(spyMockMemberLevelDao).isSpy() = true
方式二:通过Mockito.mock(xxx.class)等方法
@ExtendWith(MockitoExtension.class)
class MemberServiceImplTest {
private MemberLevelDao mockMemberLevelDao;
private MemberLevelDao spyMockMemberLevelDao;
@InjectMocks
private MemberServiceImpl memberServiceImplUnderTest;
@BeforeEach
void setUp() {
mockMemberLevelDao = Mockito.mock(MemberLevelDao.class);
spyMockMemberLevelDao = Mockito.spy(MemberLevelDao.class);
}
@Test
void testMock1() {
// 判断某对象是不是mock对象 true
System.out.println("Mockito.mockingDetails(mockMemberLevelDao).isMock() = " + Mockito.mockingDetails(mockMemberLevelDao).isMock());
// false
System.out.println("Mockito.mockingDetails(mockMemberLevelDao).isSpy() = " + Mockito.mockingDetails(mockMemberLevelDao).isSpy());
// ture mock对象包含spy对象,spy对象的mock对象的一种特殊的情况
System.out.println("Mockito.mockingDetails(spyMockMemberLevelDao).isMock() = " + Mockito.mockingDetails(spyMockMemberLevelDao).isMock());
// true
System.out.println("Mockito.mockingDetails(spyMockMemberLevelDao).isSpy() = " + Mockito.mockingDetails(spyMockMemberLevelDao).isSpy());
}
}
打印结果:(同上)
Mockito.mockingDetails(mockMemberLevelDao).isMock() = true
Mockito.mockingDetails(mockMemberLevelDao).isSpy() = false
Mockito.mockingDetails(spyMockMemberLevelDao).isMock() = true
Mockito.mockingDetails(spyMockMemberLevelDao).isSpy() = true
方式二:通过 initMocks(this);或 MockitoAnnotations.initMocks(this); 或MockitoAnnotations.openMocks(this);等方法来给本类(MemberServiceImplTest)中属性上面加了@Mock、@Spy等注解的属性创建mock对象,并赋值给这些属性/field
@ExtendWith(MockitoExtension.class)
class MemberServiceImplTest {
@Mock
private MemberLevelDao mockMemberLevelDao;
@Spy
private MemberLevelDao spyMockMemberLevelDao;
@InjectMocks
private MemberServiceImpl memberServiceImplUnderTest;
@BeforeEach
void setUp() {
initMocks(this);
MockitoAnnotations.initMocks(this);
MockitoAnnotations.openMocks(this);
}
@Test
void testMock1() {
// 判断某对象是不是mock对象 true
System.out.println("Mockito.mockingDetails(mockMemberLevelDao).isMock() = " + Mockito.mockingDetails(mockMemberLevelDao).isMock());
// false
System.out.println("Mockito.mockingDetails(mockMemberLevelDao).isSpy() = " + Mockito.mockingDetails(mockMemberLevelDao).isSpy());
// ture mock对象包含spy对象,spy对象的mock对象的一种特殊的情况
System.out.println("Mockito.mockingDetails(spyMockMemberLevelDao).isMock() = " + Mockito.mockingDetails(spyMockMemberLevelDao).isMock());
// true
System.out.println("Mockito.mockingDetails(spyMockMemberLevelDao).isSpy() = " + Mockito.mockingDetails(spyMockMemberLevelDao).isSpy());
}
2.3 参数匹配
参数匹配: 通过方法签名(参数)来指定哪些方法调用需要被处理(插桩、verify验证)
@Test
void testMock2() {
// 拦截指定类型的对象参数
Mockito.doReturn(new MemberLevelEntity()).when(mockMemberLevelDao).getGrowthPoint(ArgumentMatchers.any(String.class));//String.class 可以是自定义类型
}
2.4 方法插桩
插桩: 指定调用某个方法时的行为(stubbing),达到相互隔离的目的
插桩的用处:
-
返回指定值
-
插桩的两种方式
- when(obj.someMethod()).thenXxx():其中obj可以是mock对象
- doXxx().when(obj).someMethod():其中obj可以是mock/spy对象(没返回值的打桩常用,如果void和异常)
-
多次插桩
-
@Test void testMock2() { when(mockMemberLevelDao.getGrowthPoint(any())) .thenReturn(1).thenReturn(2).thenReturn(3); // 上面的方式也可以简写为: when(mockMemberLevelDao.getGrowthPoint(any())).thenReturn(1,2,3); // 断言getGrowthPoint()方法调用了几次 Assertions.assertEquals(1, 3); Assertions.assertEquals(2, 3); Assertions.assertEquals(3, 3); }
-
-
thenAnswer 返回指定的逻辑
-
抛出异常
-
doThrow(RuntimeException.class).when(mockMemberLevelDao).getGrowthPoint(any());
-
-
执行真正的原始方法
- 【mockito加junit搞定单元测试】 【精准空降到 04:08】 https://www.bilibili.com/video/BV1P14y1k7Hi/?p=11&share_source=copy_web&vd_source=55f99462ec0c8405d00e6ebecca29a3a&t=248
-
verify的使用
- void返回值方法插桩
两种插桩方式的区别:
【mockito加junit搞定单元测试】 https://www.bilibili.com/video/BV1P14y1k7Hi/?p=7&share_source=copy_web&vd_source=55f99462ec0c8405d00e6ebecca29a3a