各位程序员大家好。在决定将其发布到这里之前,我已经浏览了互联网上的数十种“建议”补救措施(包括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个期望。固定设置顺序并重播后,它只能被调用一次。