网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
思考一下,上一个例子当中,我可以把mockedList
的第一个数据打印出来吗?按照我们之前的逻辑当然可以,我不是有一个add
的操作吗?但是仔细想想,我们模拟的可是List
接口啊,都没有指明实现类,难道mockito
已经智能到这种程度了吗?当然不是,其实mockito对象只是具备了类的方法,但是调用方法并不会产生真实的数据,我们必须告诉mockito对象执行某种操作后,给我一个什么数据。比如上述代码中,我们执行add
操作后,给我返回一个true
或false
,好让我控制之后的程序执行路径。
package com.bootdo.app.service.impl;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import java.util.List;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@Slf4j
public class AppNoticeServiceTest {
@Test
public void baseOperation() {
List mockedList = mock(List.class);
when(mockedList.add(1)).thenReturn(Boolean.FALSE);
boolean addSuccess = mockedList.add(1);
if(addSuccess) {
// 程序略
log.info("add执行成功");
} else {
// 程序略
log.info("add执行失败");
}
}
}
此段代码我们去除了add
操作,因为add
操作并不是我们真实的目的,真实目的是我们想要控制程序的执行走的路径,达到全覆盖。
验证
验证某一方法是否执行
我们如何验证程序按照我们想要的路径争取执行了呢?可以使用verify
。Mockito verify
方法用于检查是否发生了某些行为,我们可以在测试方法代码的末尾使用Mockito
验证方法,以确保调用了指定的方法。
package com.bootdo.app.service.impl;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import java.util.List;
import static org.mockito.Mockito.*;
@Slf4j
public class AppNoticeServiceTest {
@Test
public void baseOperation() {
List mockedList = mock(List.class);
when(mockedList.get(1)).thenReturn("one");
String content =(String) mockedList.get(1);
if(content.equals("one")) {
// 程序略
mockedList.add("two");
} else {
// 程序略
mockedList.add("three");
}
verify(mockedList).add("two");
}
}
我们成功验证了mockedList
执行了add("two")
方法,证明走了true分支。
验证某一个方法执行次数
mockedList.add("three times");
mockedList.add("three times");
mockedList.add("three times");
verify(mockedList, times(3)).add("three times");
验证执行顺序
// A. Single mock whose methods must be invoked in a particular order
List singleMock = mock(List.class);
//using a single mock
singleMock.add("was added first");
singleMock.add("was added second");
//create an inOrder verifier for a single mock
InOrder inOrder = inOrder(singleMock);
//following will make sure that add is first called with "was added first", then with "was added second"
inOrder.verify(singleMock).add("was added first");
inOrder.verify(singleMock).add("was added second");
两个类的执行顺序
// B. Multiple mocks that must be used in a particular order
List firstMock = mock(List.class);
List secondMock = mock(List.class);
//using mocks
firstMock.add("was called first");
secondMock.add("was called second");
//create inOrder object passing any mocks that need to be verified in order
InOrder inOrder = inOrder(firstMock, secondMock);
//following will make sure that firstMock was called before secondMock
inOrder.verify(firstMock).add("was called first");
inOrder.verify(secondMock).add("was called second");
验证类的所有模拟方法是否都被验证了
这个方法很难理解,而且网上的资料大多数都是直译官网,非常难以理解。以下我们通过一个例子来理解一下:
public class Test {
public String method1(){return "method1";}
public String method2(){return "method2";}
}
public class MockTest {
public static void main(String[] args) {
Test test = mock(Test.class);
test.method1();
verifyNoMoreInteractions(test);
}
}
以上调用了test.method1()
但是却没有验证该结果,所以会报错。
public class MockTest {
public static void main(String[] args) {
Test test = mock(Test.class);
test.method1();
verify(test).method1();
verifyNoMoreInteractions(test);
}
}
以上的程序虽然仅仅掉了test的method1方法,没有调用test的method2方法,但是却在调用method1之后,进行了验证了执行次数(默认为1),所以verifyNoMoreInteractions就不会报错了
参数匹配
如果一个方法需要填写参数,但是输入什么参数并不是很重要,重要的是他的返回值,那么你可以使用参数匹配。
when(mockedList.get(anyInt())).thenReturn("element");
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
真正的技术提升。**
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!