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

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

                }

            });

}

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


www说
浏览 218回答 1
1回答

叮当猫咪

您是否考虑过使用 CGLib + ObjenesisHelper?CGLib 将允许您代理类和接口,而不仅仅是像 那样的接口java.lang.reflect.Proxy,并且 ObjenesisHelper 将允许您构造类的实例而无需调用构造函数。请参阅此处的 CGLib 示例和此处的 ObjenesisHelper 示例。此外,您可以解包InvocationTargetException以确保代理实例抛出Exception由模拟类定义的预期。最后, usingregisterStaticCallbacks将确保绑定的方法拦截器存在于所有调用线程中。public <T> T createProxy(final Class<? extends T> classToMock, final T mock) {&nbsp; &nbsp; final MethodInterceptor interceptor = (object, method, args, proxy) -> {&nbsp; &nbsp; &nbsp; &nbsp; synchronized (mock) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return method.invoke(mock, args);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } catch (final InvocationTargetException e) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (e.getCause() != null) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw e.getCause();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw e;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; };&nbsp; &nbsp; final Enhancer enhancer = new Enhancer();&nbsp; &nbsp; enhancer.setSuperclass(classToMock);&nbsp; &nbsp; final Set<Class<?>> interfaces = new LinkedHashSet<>();&nbsp; &nbsp; if (classToMock.isInterface()) {&nbsp; &nbsp; &nbsp; &nbsp; interfaces.add(classToMock);&nbsp; &nbsp; }&nbsp; &nbsp; interfaces.addAll(Arrays.asList(classToMock.getInterfaces()));&nbsp; &nbsp; interfaces.add(CaptureControl.class);&nbsp; &nbsp; enhancer.setInterfaces(interfaces.toArray(new Class[interfaces.size()]));&nbsp; &nbsp; enhancer.setCallbackType(interceptor.getClass());&nbsp; &nbsp; final Class<?> proxyClass = enhancer.createClass();&nbsp; &nbsp; Enhancer.registerStaticCallbacks(proxyClass, new Callback[] { interceptor });&nbsp; &nbsp; return (T) ObjenesisHelper.newInstance(proxyClass);}使用上述方法时,我遇到任何死锁的机会有多大?我不相信您提供的解决方案,也不相信上面建议的解决方案会遇到任何死锁(假设您的代码中没有死锁)。使用synchronizedwill 确保在任何给定时间只有一个线程可以操作模拟实例..并且除非 jmock 将方法调用委托给一个单独的线程(据我所知它没有),那么代码应该正常执行而不是阻塞。如果 jmock 要求您Mockery一次锁定所有实例,那么您可以传入一个专用对象进行同步,或者为所有代理拦截器提供可重入锁以共享。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java