2014-03-07 24 views
3

我使用直接Guice for DI代替GIN(在正常執行中使用)在普通Java中執行GWT應用程序的單元測試。我還使用GWTEventBinder庫(https://github.com/google/gwteventbinder)作爲事件聲明和收聽的支持庫。如何在單元測試中使用帶有guice的gwteventbinder

按照庫的要求,我爲每個聽取事件的類聲明一個EventBinder。在正常執行期間,活頁夾的實例由GIN注入。

但是在單元測試期間,實例應該由Guice生成。有關如何讓Guice生成EventBinder實例的任何想法?

回答

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反射克魯夫特的:

  1. 找到所有被註解爲@EventHandler方法。
  2. 註冊調用指定事件類型的回調方法的新處理程序。
  3. 返回一個HandlerRegistration打電話給removeHandler刪除所有在前一點添加的處理程序(此行爲是從gwteventbinder的實際實施中複製的)。

請記住,在你的@Before方法來註冊這個提供者,例如:

@Before 
public void setUpEventBindery() { 
    GwtMockito.useProviderForType(EventBinder.class, new FakeEventBinderProvider()); 
} 

你只需要爲基本接口,EventBinder做到這一點,因爲作爲GwtMockito.useProviderForType的文件說:

(..)給定的提供者應該用於GWT.create給定類型的實例,並且的子類

相關問題