Java 在多线程环境中使用模拟对象

Java 在多线程环境中使用模拟对象,java,multithreading,unit-testing,concurrency,jmock,Java,Multithreading,Unit Testing,Concurrency,Jmock,从jMock2.6开始,我可以通过 final Mockery mockery = new Mockery(); mockery.setThreadingPolicy(new Synchroniser()); 当使用jMock2.5时,我有哪些选择(我遇到间歇性测试“雪花”) 特别是,使用synchronized包装所有模拟对象方法调用是否足够(update:否,不符合预期) <T> T synchronizedMock(final T mock, final Cl

从jMock2.6开始,我可以通过

final Mockery mockery = new Mockery();
mockery.setThreadingPolicy(new Synchroniser());
当使用jMock2.5时,我有哪些选择(我遇到间歇性测试“雪花”)

特别是,使用
synchronized
包装所有模拟对象方法调用是否足够(update:否,不符合预期)

<T> T synchronizedMock(final T mock,
        final Class<T> clazz) {
    return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
            new Class[] {clazz, CaptureControl.class},
            (proxy, method, args) -> {
                synchronized (mock) {
                    return method.invoke(mock, args);
                }
            });
}
T同步锁(最终T模拟),
最后一节课(课堂){
返回(T)Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
新类[]{clazz,CaptureControl.Class},
(代理、方法、参数)->{
同步(模拟){
返回方法.invoke(mock,args);
}
});
}

使用上述方法时,我遇到死锁的机会有多大?

您是否考虑过使用CGLib+ObjenesisHelper?CGLib将允许您代理类和接口,而不仅仅是像
java.lang.reflect.proxy
这样的接口,而ObjenesisHelper将允许您构造类的实例,而无需调用构造函数。 见和

此外,您还可以解包
InvocationTargetException
,以确保代理实例抛出模拟类定义的预期
异常。最后,使用registerStaticCallbacks将确保绑定方法拦截器存在于所有调用线程中

public <T> T createProxy(final Class<? extends T> classToMock, final T mock) {
    final MethodInterceptor interceptor = (object, method, args, proxy) -> {
        synchronized (mock) {
            try {
                return method.invoke(mock, args);
            } catch (final InvocationTargetException e) {
                if (e.getCause() != null) {
                    throw e.getCause();
                }
                throw e;
            }
        }
    };

    final Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(classToMock);
    final Set<Class<?>> interfaces = new LinkedHashSet<>();
    if (classToMock.isInterface()) {
        interfaces.add(classToMock);
    }
    interfaces.addAll(Arrays.asList(classToMock.getInterfaces()));
    interfaces.add(CaptureControl.class);
    enhancer.setInterfaces(interfaces.toArray(new Class[interfaces.size()]));
    enhancer.setCallbackType(interceptor.getClass());

    final Class<?> proxyClass = enhancer.createClass();
    Enhancer.registerStaticCallbacks(proxyClass, new Callback[] { interceptor });
    return (T) ObjenesisHelper.newInstance(proxyClass);
}

public T createProxy(最终类虽然这仍然不能解决我不断失败的期望的问题,但还是谢谢你的回答。顺便说一句,我已经编辑了你的代码示例:接口列表不能为空,或者
enhancer.setInterfaces()
不应该被调用。另外,
CaptureControl
应该在模拟的接口列表中,否则jMock将拒绝设置任何期望值。