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

所以。我在JSF中启动了一个小项目。在无法使用JSFUnit和Apache Cactus测试UIComponents与托管Bean之间的关系之后(这是另一个可悲的故事),我希望至少能够测试域模型单元。唉。

我有这个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();


}

是的,摘录自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

任何提示表示赞赏。

最佳答案

你有倒退。

在调用实际的被测系统(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个期望。固定设置顺序并重播后,它只能被调用一次。

08-18 10:32