我在普通Java中使用Guice for DI而不是GIN(在正常执行中使用)执行GWT应用程序的单元测试。我还使用GWTEventBinder库(https://github.com/google/gwteventbinder)作为事件声明和监听的支持库。
根据库的要求,我为每个听取事件的类声明了一个EventBinder。在正常执行期间,绑定器的实例由GIN注入。
然而,在单元测试期间,实例应由Guice生成。关于如何让Guice生成EventBinder实例的任何想法?
答案 0 :(得分:1)
根据issue对gwteventbinder项目(您报告:)的评论和建议,我已经提出以下代码:
public class FakeEventBinderProvider implements FakeProvider<EventBinder<?>> {
@Override
public EventBinder<?> getFake(Class<?> type) {
return (EventBinder<?>) Proxy.newProxyInstance(FakeEventBinderProvider.class.getClassLoader(), new Class<?>[] { type }, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, final Object[] args) throws Throwable {
String methodName = method.getName();
assert methodName.equals("bindEventHandlers");
final List<HandlerRegistration> registrations = new LinkedList<HandlerRegistration>();
EventBus eventBus = (EventBus) args[1];
List<Method> presenterMethods = getAllMethods(args[0].getClass());
for (final Method presenterMethod : presenterMethods) {
if (presenterMethod.isAnnotationPresent(EventHandler.class)) {
@SuppressWarnings("unchecked") // Should always be ok, since the Generator for EventBinder should do all the safe-checking
Class<? extends GenericEvent> eventType = (Class<? extends GenericEvent>) (presenterMethod.getParameterTypes())[0];
registrations.add(eventBus.addHandler(GenericEventType.getTypeOf(eventType), new GenericEventHandler() {
@Override
public void handleEvent(GenericEvent event) {
try {
presenterMethod.setAccessible(true);
presenterMethod.invoke(args[0], event);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
}));
}
}
return new HandlerRegistration() {
@Override
public void removeHandler() {
for (HandlerRegistration registration : registrations) {
registration.removeHandler();
}
registrations.clear();
}
};
}
});
}
private List<Method> getAllMethods(Class<?> type) {
List<Method> methods = new LinkedList<Method>();
methods.addAll(Arrays.asList(type.getDeclaredMethods()));
if (type.getSuperclass() != null) {
methods.addAll(getAllMethods(type.getSuperclass()));
}
return methods;
}
}
根据建议,我已根据FakeUiBinderProvider
的实施情况进行了此操作。
一旦你摆脱了Java Reflection cruft,它就非常简单了:
@EventHandler
注释的所有方法。HandlerRegistration
,调用removeHandler
时会删除上一点中添加的所有处理程序(此行为是从gwteventbinder的实际实现中复制而来的)。请记住注册此提供商,例如在@Before
方法中注册:
@Before
public void setUpEventBindery() {
GwtMockito.useProviderForType(EventBinder.class, new FakeEventBinderProvider());
}
您只需要为基本界面EventBinder
执行此操作,因为GwtMockito.useProviderForType
的文档说:
(..)给定的提供者应该用于GWT.create给定类型的实例和它的子类。