mockito源码研究之verify
一、Mockito类相当于整个框架的门面,负责对外提供调用接口。常用的有如下几个:
mock
List list = Mockito.mock(List.class); 此时, list就是被Mockito所mock后生成的实例,Mockito会记住它所mock对象的所有调用,为后面的验证做准备。
when
Mockito.when(list.size()).thenReturn(1);
上述代码表示,当对list对象调用size()方法时,会返回1.这样我们就可以自定义mock对象的行为了。
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):执行次数
verify是负责验证的函数,接受的参数是一个被mock的对象,表示验证其是否执行了后面的方法。
二、疑问点
verify函数怎么会知道哪些方法被调用了呢?是动态代理吗?
三、源码深入
1. 入口类Mockito
public static T verify(T mock, VerificationMode mode) { // 常用的验证模式: AtLeast(最少)、AtMost(最多)、Times(次数)
return MOCKITO_CORE.verify(mock, mode); //
}
2. 核心实现逻辑
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函数只是做了一些准备工作, 首先,VerificationMode是对验证信息的封装,它是一个接口,含有verify函数, 例如我们常用的never(). times(1)返回的都是Times类型,而Times类型就是VerificationMode的一种实现。然后,调用mockingProgress 来缓存mode信息。
>>> 函数的最后直接将mock对象返回,VerificationMode并没有被执行,因为在verify函数后紧跟着就是调用mock对象的doSome()方法。
3. 抽象验证类(MockAwareVerificationMode)
public void verify(VerificationData data) {
try {
mode.verify(data); // 通过传入的验证模式来验证数据,这里是一个命令模式,将动作的执行,封装在命令中。
notifyListeners(new VerificationEventImpl(mock, mode, data, null)); // 这里是一个观察者模式,将验证数据广播出去
}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模式的验证
public void verify(VerificationData data) {
List invocations = data.getAllInvocations();
MatchableInvocation wanted = data.getTarget();
if (wantedCount >0) {
checkMissingInvocation(data.getAllInvocations(), data.getTarget()); // 这里只是作为一种日志补偿输出
}
checkNumberOfInvocations(invocations, wanted, wantedCount); // 将缓存的调用信息与期望值进行比较
}
5. verify.doSome() 实现
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信息,然后当验证信息不为空时,验证mode的状态是否正确,当一切无误是调用verificationMode的verify方法,完成验证
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());