Java 在多线程环境中使用模拟对象
从jMock2.6开始,我可以通过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
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将拒绝设置任何期望值。