我正在用纯java执行gwt应用程序的单元测试,直接使用guice for di而不是gin(在正常执行中使用)。我还使用gwteventbinder库(https://github.com/google/gwteventbinder)作为事件声明和侦听的支持库。
根据库的要求,我为监听事件的每个类声明一个eventbinder。在正常执行期间,绑定器的实例由gin注入。
但是在单元测试期间,该实例应该由guice生成。你知道如何让guice生成eventbinder实例吗?
最佳答案
根据anissue对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反射的障碍:
找到所有用
@EventHandler
注释的方法。注册一个新的处理程序,为指定的事件类型调用回调方法。
返回一个
HandlerRegistration
调用时返回的removeHandler
将删除前一点中添加的所有处理程序(此行为从gwteventbinder的实际实现中复制)。请记住注册此提供程序,例如在
@Before
方法中:@Before
public void setUpEventBindery() {
GwtMockito.useProviderForType(EventBinder.class, new FakeEventBinderProvider());
}
您只需要对基本接口
EventBinder
执行此操作,因为正如GwtMockito.useProviderForType
的文档所示:(..)应使用给定的提供程序来gwt.create给定类型及其子类的实例。