假设我的Interface方法有一个验证注释来验证输入参数和返回值。 目前是否有可能(V 1.9.5)告诉Mockito在调用过程中调用此验证器?
背景是防止开发人员通过以违反指定验证器的方式模拟给定接口来编写不切实际的测试。
所以我想要的是注册类似
的东西class MyAnswerInterceptor<T> implements AnswerInterceptor<T> {
@Override
public Answer<T> intercept(final Answer<T> answer) {
return new Answer<T>() {
@Override
public T answer(InvocationOnMock invocation) throws Throwable {
validateArguments(invocation);
T result = answer.answer(invocation);
validateReturnValue(result);
return result;
}
}
}
}
在给定模拟的每个答案上调用。
这有可能吗?我已经查看了代码,也检查了我是否可以在某个时刻入侵(甚至使用反射等),但似乎是由于实例创建和逻辑的纠缠,它几乎不可能实现我想要的东西(即像MockHandler mockHandler = new MockHandlerFactory().create(settings);
这样的东西使得无法挂钩并将自定义内容放在顶部而无需修补和部署整个东西......)
任何见解都会受到高度赞赏: - )
答案 0 :(得分:2)
您可以通过创建自定义MockMaker
来实现这一目标。
MockMaker是一个扩展点,可以使用自定义动态代理并避免使用默认的cglib / asm / objenesis实现
我们的自定义实现会将所有复杂内容委托给默认的MockMaker
:CglibMockMaker
。它装饰&#34;仅通过在settings
参数createMock
上注册InvocationListener
方法。完成invocation
后,系统会通知此听众,以便拨打validateArguments
和validateReturnValue
。
import org.mockito.internal.creation.CglibMockMaker;
import org.mockito.invocation.Invocation;
import org.mockito.invocation.MockHandler;
import org.mockito.listeners.InvocationListener;
import org.mockito.listeners.MethodInvocationReport;
import org.mockito.mock.MockCreationSettings;
import org.mockito.plugins.MockMaker;
public class ValidationMockMaker implements MockMaker {
private final MockMaker delegate = new CglibMockMaker();
public ValidationMockMaker() {
}
@Override
public <T> T createMock(MockCreationSettings<T> settings, MockHandler handler) {
settings.getInvocationListeners().add(new InvocationListener() {
@Override
public void reportInvocation(MethodInvocationReport methodInvocationReport) {
Invocation invocation = (Invocation) methodInvocationReport.getInvocation();
validateArguments(invocation.getArguments());
validateReturnValue(methodInvocationReport.getReturnedValue());
}
});
return delegate.createMock(settings, handler);
}
@Override
public MockHandler getHandler(Object mock) {
return delegate.getHandler(mock);
}
@Override
public void resetMock(Object mock, MockHandler newHandler, MockCreationSettings settings) {
delegate.resetMock(mock, newHandler, settings);
}
protected void validateArguments(Object... arguments) {
// Arrays.stream(arguments).forEach(Objects::requireNonNull);
}
private void validateReturnValue(Object result) {
// Objects.requireNonNull(result);
}
}
最后但并非最不重要的是,我们需要告诉Mockito使用我们的实现。这可以通过添加文件
来实现mockito-extensions/org.mockito.plugins.MockMaker
包含我们的MockMaker类名:
ValidationMockMaker
请参阅javadoc中的Using the extension point
部分。