2015-09-14 51 views
2

你好同胞程序員。在我決定在這裏發佈之前,我已經瀏覽了互聯網上幾十種「建議」的補救措施(包括在計算器上)。但無濟於事。Junit和EasyMock意外的失敗

所以。我在JSF開始了一個小項目。在未能使用JSFUnit和Apache Cactus測試UIComponent和Managed Beans之間的關係(這是另一個令人傷心的故事)之後,我希望至少能夠測試域模型單元。唉。

我有這樣的POJO:

public class AppointmentFormBean implements Serializable, Observed{ 
private Date selectedDate; 
private ArrayList<VGObserver> observers; 
/** 
* Creates a new instance of AppointmentFormBean 
*/ 
public AppointmentFormBean() { 
    observers = new ArrayList<>(); 
} 

public Date getSelectedDate() { 
    return selectedDate; 
} 

public void setSelectedDate(Date selectedDate) { 
    this.selectedDate = selectedDate; 
    notifyVGObservers(); 
} 

@Override 
public void registerVGObserver(VGObserver o) { 
    this.observers.add(o); 
} 

@Override 
public void removeVGObserver(VGObserver o) { 
    int i = observers.indexOf(o); 
    if(i>=0) 
     observers.remove(o); 
} 

@Override 
public void notifyVGObservers() { 
    observers.stream().map((observer1) -> (VGObserver) observer1).forEach((observer) -> { 
     observer.update(selectedDate); 
    }); 
} 

}

(我故意省略JSF的註解 - 他們是無關緊要的,因爲我跑的測試)

觀察到的接口,該POJO工具看起來像這個:

public interface Observed { 
public void registerVGObserver(VGObserver o); 
public void removeVGObserver(VGObserver o); 
public void notifyVGObservers(); 

}

業,從Head First設計模式,誰讀過它:-)

VGObserver,上面提到的複製 - 是另一種界面,將「聽」到的類的變化實施觀察:

public interface VGObserver { 
public void update(Date selectedDate); 

}

我對這個設計的大計劃,爲最終VGObserver(具體的類實現它)會嘗試檢索REST資源 - 天氣所傳遞的日期。但我們離題了。

最後,我已經建立了我的測試類來檢查,每次setSelectedBean(...)被調用時,VGObserver的更新(...)被觸發。我用簡易模擬嘲笑VGObserver接口:

public class AppointmentBeanObservableTest { 

private AppointmentFormBean form; 
private VGObserver mockObserver; 
private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); 

@Before 
public void setUp() { 
    form = new AppointmentFormBean(); 
    mockObserver = createMock("observer", VGObserver.class); 
    form.registerVGObserver(mockObserver); 
} 

@After 
public void tearDown() { 
    verify(mockObserver); 
} 

@Test 
public void testIocForVGObserved() throws ParseException {   
    Date aDate = sdf.parse("2015-09-15"); 
    form.setSelectedDate(aDate); 
    mockObserver.update(aDate); 
    EasyMock.expectLastCall().anyTimes(); 
    replay(mockObserver); 
} 

}

遺憾的是本次測試失敗,莊嚴,有什麼我可以找到縫補。下面是在github輸出和項目鏈接:

Time elapsed: 0.091 sec <<< FAILURE! 
java.lang.AssertionError: Expectation failure on verify: 
observer.update(Tue Sep 15 00:00:00 EDT 2015): expected: at least 1, actual: 0 
at org.easymock.internal.MocksControl.verify(MocksControl.java:241) 
at org.easymock.EasyMock.verify(EasyMock.java:2100) 
at com.vgorcinschi.rimmanew.model.AppointmentBeanObservableTest.tearDown(AppointmentBeanObservableTest.java:40) 

Results : 
Failed tests: 
AppointmentBeanObservableTest.tearDown:40 
Expectation failure on verify: 
observer.update(Tue Sep 15 00:00:00 EDT 2015): expected: at least 1, actual: 0 
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0 

https://github.com/vasigorc/rimmaproject

任何暗示表示讚賞。

回答

2

你有它倒退。

在調用實際被測系統(SUT)之前,您必須告訴模擬會發生什麼。然後在設定好預期後,您可以在replay模式下進行模擬。最後你打電話給你的系統進行測試。

你首先調用你的系統,然後設置你的模擬。

將其更改爲:

@Test 
public void testIocForVGObserved() throws ParseException {   
    Date aDate = sdf.parse("2015-09-15"); 

    mockObserver.update(aDate); 
    EasyMock.expectLastCall().anyTimes(); 
    replay(mockObserver); 

    //call SUT now 
    form.setSelectedDate(aDate); 
} 

應該工作。

您也可以刪除expectLastCall().anyTimes()行。由於模擬期望呼叫處於記錄模式的實施細節,您的倒退設置可能會爲呼叫設置2個預期。一旦你解決了設置和重播的順序,它只應該被調用一次。

+0

dkatzel,這是正確的答案! JUnit酒吧是綠色的,我很高興:-) 不幸的是我沒有足夠的聲望給這個+1,但非常感謝。我們有一個勝利者。 – vasigorc