2013-08-02 49 views
0

我想單元測試現有的ZK控制器,我想找到一種方法來處理調用諸如以下,而單元測試我控制器,我如何設置ZK會話(org.zkoss.zk.ui),以便我可以單元測試控制器類擴展GenericForwardComposer

Sessions.getCurrent().setAttribute("from", from.getValue()); 

我很樂意要麼更換有問題的代碼,或者找到變通的辦法進行單元測試。我的目標是通過與NullPointerException

我的測試是簡單的可測試性處理(這不是太糟糕一開始的地方......)控制器的

@Test 
    public void zkControllerDoesMockingInitialisedSuccessfully() throws Exception { 

    T2TripBigDaoInterface tripBigDao = createMock(T2TripBigDao.class); 
    ZkFieldValidator fieldValidator = createMock(ZkTextFieldValidator.class); 
    FieldRangeValidator rangeValidator = createMock(DefaultFieldRangeValidator.class); 

    TripController controller = new TripController(tripBigDao, fieldValidator, rangeValidator); 


    replay(tripBigDao, fieldValidator, rangeValidator); 

    controller.onClick$getTrips(new Event("getTrips")); 

    verify(tripBigDao, fieldValidator, rangeValidator); 

    // Test purpose: Just get a unit test of the controller running to start with.... 
} 


提取物:

public class TripController extends GenericForwardComposer { 

.... 

    public void onClick$getTrips(Event event) throws Exception { 
     Sessions.getCurrent().setAttribute("from", from.getValue()); 
     Sessions.getCurrent().setAttribute("to", to.getValue()); 

     .... 
    } 
.... 


提取的堆棧跟蹤:

java.lang.NullPointerException 
at com.t2.webservice.controller.alert.TripController.onClick$getTrips(TripController.java:72) 
at com.t2.webservice.controller.alert.TripControllerTest.zkControllerDoesMockingInitialisedSuccessfully(TripControllerTest.java:45) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 

回答

1

這是我最不喜歡ZK的東西之一:他們使用單例和對可測試性的影響。

我最終做的是從我的控制器中刪除對其單例的所有引用(Sessions,Executions,Selectors)。在正常的操作中,這些單身使用,但在測試中,他們可以被嘲笑。

你如何去做這件事取決於你,我還沒有找到我愛上的模式。
這裏有一個想法..

public class TripController extends GenericForwardComposer { 

    private final TripSessionManager tripSessionManager; 

    public TripController() { 
     // ZK calls the default constructor 
     this(new ZKTripSessionManager()); 
    } 

    protected TripController(TripSessionManager tripSessionManager) { 
     this.tripSessionManager = tripSessionManager; 
    } 

    public void onClick$getTrips(Event event) throws Exception { 
     tripSessionManager.setTo(to.getValue()); 
     tripSessionManager.setFrom(from.getValue()); 
    } 

} 

TripSessionManager會再看看這樣的..

public interface TripSessionManager { 

    void setTo(String to); 

    void setFrom(String from); 

} 

使用默認ZK實現依靠Sessions單..

public ZKTripSessionManager implements TripSessionManager { 

    public void setTo(String to) { 
     setAttribute("to", to); 
    } 

    public void setFrom(String from) { 
     setAttribute("from", from); 
    } 

    private void setAttribute(String name, String value) { 
     // only valid if called in a ZK managed thread 
     Sessions.getCurrent().setAttribute(name, value); 
    } 

} 

通過抽象出實現,你可以用模擬TripSessionManager來測試你的控制器。

@Test 
public void test() { 
    TripSessionManager mockTripSessionManager = mock(TripSessionManager); 
    when(mockTripSessionManager.setTo(anyString()).thenAnswer(...); 
    when(mockTripSessionManager.setFrom(anyString()).thenAnswer(...); 
    TripController controller = new TripController(mockTripSessionManager); 
} 

你也可以想像管理這些新的依賴不同的方式(如:避免new ZKTripSessionManager())使用像Spring或Guice的依賴注入框架。

相關問題