gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-03 12:59:04 25 4
gpt4 key购买 nike

从 jMock 开始2.6 ,我可以确保我的模拟对象通过多个线程一致地看到

final Mockery mockery = new Mockery();
mockery.setThreadingPolicy(new Synchroniser());

使用 jMock 时我有哪些选择(我正在经历间歇性测试“薄片”) 2.5 ?

特别是,使用 synchronized 包装所有模拟对象方法调用是否足够( 更新 :不,不符合预期) ?
<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);
}
});
}

使用上述方法时,我遇到任何死锁的机会是什么?

最佳答案

您是否考虑过使用 CGLib + ObjenesisHelper? CGLib 将允许您代理类和接口(interface),而不仅仅是像 java.lang.reflect.Proxy 这样的接口(interface)。 ,并且 ObjenesisHelper 将允许您构造类的实例,而无需调用构造函数。
here for a CGLib examplehere for a ObjenesisHelper example .

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

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);
}

When using the above approach, what are my chances to run into any deadlocks?



我不相信您提供的解决方案,也不相信上面建议的解决方案会遇到任何死锁(假设您的代码中已经没有死锁)。使用 synchronized将确保在任何给定时间只有一个线程可以操作模拟实例。除非 jmock 将方法调用委托(delegate)给一个单独的线程(据我所知,它没有),否则代码应该正常执行而不是阻塞。如果 jmock 要求您锁定所有 Mockery实例,然后您可以传入一个专用对象以进行同步,或者为所有代理拦截器共享一个可重入锁。

关于java - 在多线程环境中使用模拟对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51965601/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com