6

假设我的接口方法上有一个验证注释来验证输入参数和返回值。目前(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);的东西,如果不打补丁和部署整个东西,就不可能钩住并把自定义的东西放在上面......)

任何见解将不胜感激:-)

4

1 回答 1

2

您可以通过创建自定义MockMaker.

MockMaker 是一个扩展点,可以使用自定义动态代理并避免使用默认的 cglib/asm/objenesis 实现

我们的自定义实现将所有复杂的东西委托给默认的MockMaker: CglibMockMaker。它通过在参数 an上注册仅“装饰”该createMock方法。当一个已经完成允许使用调用和时,将通知此侦听器。settingsInvocationListenerinvocationvalidateArgumentsvalidateReturnValue

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

请参阅Using the extension pointjavadoc 中的部分。

于 2014-07-16T15:23:48.457 回答