一、Mockito類相當(dāng)于整個(gè)框架的門面,負(fù)責(zé)對(duì)外提供調(diào)用接口。常用的有如下幾個(gè):
mock
? List list = Mockito.mock(List.class);? 此時(shí), list就是被Mockito所mock后生成的實(shí)例,Mockito會(huì)記住它所mock對(duì)象的所有調(diào)用,為后面的驗(yàn)證做準(zhǔn)備。
when
? Mockito.when(list.size()).thenReturn(1);
上述代碼表示,當(dāng)對(duì)list對(duì)象調(diào)用size()方法時(shí),會(huì)返回1.這樣我們就可以自定義mock對(duì)象的行為了。
verify
? Mockito.verify(list).add(Matchers.anyObject());
? Mockito.verify(reserveManager).findByTradeOrderId(Mockito.any());
? Mockito.verify(reserveManager,Mockito.times(1)).findByTradeOrderId(Mockito.any());? Mockito.times(1):執(zhí)行次數(shù)
verify是負(fù)責(zé)驗(yàn)證的函數(shù),接受的參數(shù)是一個(gè)被mock的對(duì)象,表示驗(yàn)證其是否執(zhí)行了后面的方法。
二、疑問點(diǎn)
verify函數(shù)怎么會(huì)知道哪些方法被調(diào)用了呢?是動(dòng)態(tài)代理嗎?
三、源碼深入
1. 入口類Mockito
public static T verify(T mock, VerificationMode mode) {? ? // 常用的驗(yàn)證模式:?AtLeast(最少)、AtMost(最多)、Times(次數(shù))
? ?return MOCKITO_CORE.verify(mock, mode);? //?
}
2. 核心實(shí)現(xiàn)邏輯
public T verify(T mock, VerificationMode mode) {
if (mock ==null) {
throw nullPassedToVerify();
? ? }
if (!isMock(mock)) {
throw notAMockPassedToVerify(mock.getClass());
? ? }
? ? MockingProgress mockingProgress =mockingProgress();
? ? VerificationMode actualMode = mockingProgress.maybeVerifyLazily(mode);
? ? mockingProgress.verificationStarted(new MockAwareVerificationMode(mock, actualMode, mockingProgress.verificationListeners()));
? ? return mock;
}
>>> 可見verify函數(shù)只是做了一些準(zhǔn)備工作, 首先,VerificationMode是對(duì)驗(yàn)證信息的封裝,它是一個(gè)接口,含有verify函數(shù), 例如我們常用的never(). times(1)返回的都是Times類型,而Times類型就是VerificationMode的一種實(shí)現(xiàn)。然后,調(diào)用mockingProgress 來緩存mode信息。
>>>? 函數(shù)的最后直接將mock對(duì)象返回,VerificationMode并沒有被執(zhí)行,因?yàn)樵趘erify函數(shù)后緊跟著就是調(diào)用mock對(duì)象的doSome()方法。
3. 抽象驗(yàn)證類(MockAwareVerificationMode)
public void verify(VerificationData data) {
try {
? ? ? ?mode.verify(data);? // 通過傳入的驗(yàn)證模式來驗(yàn)證數(shù)據(jù),這里是一個(gè)命令模式,將動(dòng)作的執(zhí)行,封裝在命令中。
? ? ? ? notifyListeners(new VerificationEventImpl(mock, mode, data, null));? // 這里是一個(gè)觀察者模式,將驗(yàn)證數(shù)據(jù)廣播出去
? ? }catch (RuntimeException e) {
notifyListeners(new VerificationEventImpl(mock, mode, data, e));
? ? ? ? throw e;
? ? }catch (Error e) {
notifyListeners(new VerificationEventImpl(mock, mode, data, e));
? ? ? ? throw e;
? ? }
}
4. Times模式的驗(yàn)證
public void verify(VerificationData data) {
List invocations = data.getAllInvocations();
? ? MatchableInvocation wanted = data.getTarget();
? ? if (wantedCount >0) {
? ? ? ?checkMissingInvocation(data.getAllInvocations(), data.getTarget());? // 這里只是作為一種日志補(bǔ)償輸出
? ? }
? ? ? ?checkNumberOfInvocations(invocations, wanted, wantedCount);? // 將緩存的調(diào)用信息與期望值進(jìn)行比較
}
5.?verify.doSome() 實(shí)現(xiàn)
MockHandlerImpl的handle
VerificationMode verificationMode = mockingProgress.pullVerificationMode();
if (verificationMode != null) {
if (((MockAwareVerificationMode) verificationMode).getMock() == invocation.getMock()) {
VerificationDataImpl data = createVerificationData(invocationContainerImpl, invocationMatcher);
verificationMode.verify(data); return null; }
else { ... }
}
先獲取mockingProgress中緩存的verificationMode信息,然后當(dāng)驗(yàn)證信息不為空時(shí),驗(yàn)證mode的狀態(tài)是否正確,當(dāng)一切無誤是調(diào)用verificationMode的verify方法,完成驗(yàn)證
6. 方法攔截源碼:SubclassBytecodeGenerator
public ClassmockClass(MockFeatures features) {
DynamicType.Builder builder =
byteBuddy.subclass(features.mockedType)
.name(nameFor(features.mockedType))
.ignoreAlso(isGroovyMethod())
.annotateType(features.mockedType.getAnnotations())
.implement(new ArrayList(features.interfaces))
.method(matcher)
.intercept(to(DispatcherDefaultingToRealMethod.class))
.transform(withModifiers(SynchronizationState.PLAIN))
.attribute(INCLUDING_RECEIVER)
.method(isHashCode())
.intercept(to(MockMethodInterceptor.ForHashCode.class))
.method(isEquals())
.intercept(to(MockMethodInterceptor.ForEquals.class))
.serialVersionUid(42L)
.defineField("mockitoInterceptor", MockMethodInterceptor.class, PRIVATE)
.implement(MockAccess.class)
.intercept(FieldAccessor.ofBeanProperty());