总结来说,测试的种类主要有以下几类
Mock是什么?
使用Mock能够为我们带来哪些好处呢?
对于开发人员来说,使用Mock有哪些作用呢?
Mock与Stub(桩):
简而言之,Mockito是一款在java中比较出名且优秀的单元测试工具;
Mockito是一个单元测试框架,封装了简洁易用的API,对于新手来说也可以很容易的入门,同时在我们编写单元测试的时候还可以以锻炼我们的逻辑思维能力。
@Mock
private ImageSercice imageSercice;
@Mock
private RiskSercice riskSercice;
@InjectMocks
private UserSercice userSercice;
@Test
public void testWhen() {
Mockito.when(imageService.upload(Mockito.any())).thenReturn(true);
Mockito.when(riskService.risk(Mockito.anyMap())).thenReturn(new HashMap());
userService.save(new HashMap<>());
}

// 保存用户的时候抛出Exception异常
Mockito.doThrow(new NullPointerException()).when(Mockito.mock(UserService.class)).save(null);
Mockito.when(userService.getById(1)).thenReturn(userModel);
// 当单个参数是,可以改写成
Mockito.when(userService.getById(Mockito.eq(1))).thenReturn(userModel);
// 多个参数,校验的Mockito参数类型参数不同,此种情况每个参数都必须添加特定类型参数值校验,
// 示例demo:userService.get(age,name,date)
// 错误写法
Mockito.when(userService.get(1,null,new Mockito.isA(Date.class))).thenReturn(userModel);
// 正确写法
Mockito.when(userService.get(Mockito.eq(1),Mockito.isNull(),Mockito.isA(Date.class))).thenReturn(userModel);
// 也是正确写法,但是new Date 与程序中的new Date是两个对象,不会命中预设值的Mockito.when(userService.get(1,null,new Date())).thenReturn(userModel);
Mockito.when(userService.get(1,null,new Date())).thenReturn(userModel);
// 与 Mockito.eq 中的demo类似 ,只是将Mockito.isA 换成了any
Mockito.when(userService.get(Mockito.eq(1),Mockito.isNull(),Mockito.any(Date.class))).thenReturn(userModel);
// 与 Mockito.any 中的demo类似
Mockito.when(userService.get(Mockito.eq(1),Mockito.isNull(),Mockito.any(Date.class))).thenReturn(userModel);
// 与 Mockito.any 中的demo类似
Mockito.when(userService.get(Mockito.eq(1),Mockito.isNull(),Mockito.any(Date.class))).thenReturn(userModel);
// 校验 riskService.risk 方法被调用一次
Mockito.verify(riskService, Mockito.times(1)).risk(Mockito.any(RiskModel.class));
// 校验 riskService.risk 方法被调用一次:Mockito.times(次数)
Mockito.verify(riskService, Mockito.times(1)).risk(Mockito.any(RiskModel.class));
userService.save(userModel);
// 验证通过
Mockito.verify(riskService, Mockito.times(1)).risk(Mockito.any(RiskModel.class));
// 重置已经统计的次数
Mockito.reset(userService);
userService.save(userModel);
// 验证通过
Mockito.verify(riskService, Mockito.times(1)).risk(Mockito.any(RiskModel.class));
总之,可以先记住我们的过程主要分为三个:Mock数据->设定预期->验证结果。要注意其中设定预期是可以被省略的。至于里面的方法,忘了可以再回来看或者翻官方文档;
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.8.0</version>
<scope>test</scope>
</dependency>
public class Person{
private int id;
private String name;
private String key;
public Person(int id,String name){
this.id = id;
this.name = name;
this.key = id + name + id;
}
// setter、getter方法省略
}
public class PersonTest{
@Test
void verifyTest(){
Person mockPerson = mock(Person.class);
mockPerson.setId(1);
mockPerson.setName("TestOps");
verify(mockPerson).setId(1);
verify(mockPerson).setName("TestOps");
}
}
验证了setId(1)和 setName(“TestOps”)这两个方法是否被调用了;
@Test
void subTest{
Person mockPerson = mock(Person.class);
when(mockPerson.getId()).thenReturn(1);
when(mockPerson.getName()).thenThrow(new NoSuchMethodError());
// 单元测试通过
System.out.println(mockPerson.getId());
// 单元测试抛出异常
System.out.println(mockPerson.getName());
}
public String setKeyById(int id){
this.key = id + this.name + id;
return this.key;
}
@Test
void matchersTest(){
Person mockPerson = mock(Person.class);
when(mockPerson.setKeyById(anyInt())).thenReturn("00testops00");
System.out.println(mockPerson.setKeyById(5));
verify(mockPerson).setKeyById(anyInt());
}
@Test
void timesTest(){
Person mockPerson = mock(Person.class);
mockPerson.setId(1);
verify(mockPerson).setId(1);
mockPerson.setName("testops");
mockPerson.setName("testops");
verify(mockPerson,times(2)).setName("testops");
verify(mockPerson,atLeast(2)).setName("testops");
verify(mockPerson,never()).setId(2);
}
@Test
void orderTest(){
Person singleMock = mock(Person.class);
singleMock.setId(1);
singleMock.setId(2);
InOrder inOrder = inOrder(singleMock);
inOrder.verify(singleMock).setId(1);
inOrder.verify(singleMock).setId(2);
Person firstMock = mock(Person.class);
Person secondMock = mock(Person.class);
firstMock.setId(1);
secondMock.setId(2);
InOrder inOrderT = inOrder(firstMock,secondMock);
// 这里会抛出异常,因为执行setId(2)的方法在set(1)的方法之后执行的;
inOrder1.verify(secondMock).setId(2);
inOrder1.verify(firstMock).setId(1);
}
@Test
void consecutiveStubTest(){
Person personMock = mock(Person.class);
when(personMock.getName())
.thenReturn("testops")
.thenThrow(new NoSuchElementException());
System.out.println(personMock.getName()); // testops
System.out.println(personMock.getName()); // 异常
}
@Test
void spyTest(){
Person person = new Person(1,"testops");
Person spy = spy(person);
when(spy.getName()).thenReturn("mango");
System.out.println(spy.getId());
System.out.println(spy.getName());
// 使用spy对象时真实的对象也会被调用,除非它被Mock了;
// 所以,当真实对象不可被调用时,请使用doReturn | Answer | Throw()
doReturn("1testops1").when(spy).setKeyById(-1);
System.out.println(spy.setKeyById(-1));
}






