【问题标题】:Junit and EasyMock unexpected failureJunit 和 EasyMock 意外失败
【发布时间】:2015-09-14 00:06:12
【问题描述】:

各位程序员大家好。在我决定在这里发布之前,我已经浏览了互联网上的数十种“建议”补救措施(包括在 stackoverflow 上)。但无济于事。

所以。我在 JSF 中开始了一个小项目。在使用 JSFUnit 和 Apache Cactus 测试 UIComponents 和 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 实现的 Observed 接口如下所示:

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

}

Yip,抄自 Head First Design Patterns,谁读过它:-)

上面提到的 VGObserver - 是另一个接口,它将“监听”实现 Observed 的类的变化:

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

}

我对此设计有很大的计划,因为最终 VGObserver(实现它的具体类)将尝试检索 REST 资源 - 过去日期的天气。但我们离题了。

最后我构建了我的测试类来检查每次调用 setSelectedBean(...) 时,是否触发了 VGObserver 的 update(...)。我使用 Easy Mock 来模拟 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

感谢任何提示。

【问题讨论】:

    标签: java jsf junit observer-pattern easymock


    【解决方案1】:

    你倒过来了。

    在调用实际的被测系统 (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 个期望。一旦你修复了设置的顺序并重放它应该只被调用一次。

    【讨论】:

    • dkatzel,这是正确的答案! JUnit 条是绿色的,我很高兴 :-) 不幸的是,我没有足够的声誉来对此进行 +1,但非常感谢。我们有一个赢家。
    猜你喜欢
    • 2011-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多