在 GWT 的教程中,Google 使用不同的方法来执行 MVP,View 指定 Presenter 或 Presenter 指定 View。第一个在使用活动和地点时使用。
这篇文章涉及到这个主题:MVP:视图是否应该实现演示者的接口,反之亦然?
但是,我想知道在对演示者和视图进行单元测试时,您认为哪种替代方案最好?还是两者都同样有效?
在 GWT 的教程中,Google 使用不同的方法来执行 MVP,View 指定 Presenter 或 Presenter 指定 View。第一个在使用活动和地点时使用。
这篇文章涉及到这个主题:MVP:视图是否应该实现演示者的接口,反之亦然?
但是,我想知道在对演示者和视图进行单元测试时,您认为哪种替代方案最好?还是两者都同样有效?
Presenter 单元测试背后的想法是模拟视图,并针对这个模拟视图的状态编写几个断言,这些断言将在现实生活中的应用程序中以视觉方式表示。多亏了这种方法,不需要运行 full GWTTestCase
,这会花费大量时间,并且应该放在集成测试的类别中,而不是单元测试的类别中。
如果您尝试两种 MVP 方法,单元测试可能如下所示:
MVP 1:
@Test
public void shouldAddContactOnAddContactClicked() {
// given
ContactsPresenter.Display display = mock(ContactsPresenter.Display.class);
MockButton addButton = new MockButton();
given(display.getAddButton()).willReturn(addButton);
ContactsDisplay.Presenter presenter = new ContactsPresenter();
presenter.bindView(display);
presenter.setContacts(new ArrayList<Contact>());
// when
addButton.click();
// then
verify(display).addContact(any());
assertThat(presenter.getContacts().size(), is(1));
}
MockButton
我在这里描述的东西
在哪里: GWT 模拟框架的综合优点/缺点
尽管可能,但以这种方式模拟事物并不是很方便。MVP2 方法似乎表现更好:
@Test
public void shouldAddContactOnAddContactClicked() {
// given
ContactsView view = mock(ContactsView.class);
ContactsView.Presenter presenter = new ContactsPresenter();
presenter.bindView(view); // assuming that presenter will call view.setPresenter(this)
presenter.setContacts(new ArrayList<Contact>());
// when
presenter.onAddContactClicked();
// then
verify(view).addContact(any());
assertThat(presenter.getContacts().size(), is(1));
}
使用第二种方法的另一个原因是 MVP1 中声明显示元素的问题,这将触发不同的事件(例如 ClickEvent、FocusEvent)。MVP2 还使事情变得更容易UiBinder
。
避免使用HasXxxHandlers
,即使用第2 部分文章中的方法,其中每个对等点都引用另一个。HasXxxHandlers
模拟起来太复杂了,尤其是在使用 Mockito 或 EasyMock 等模拟库时。为了获得最佳可测试性,您将视图注入演示者,然后演示者将调用视图的setPresenter
orsetDelegate
方法(这样,您可以在正确的时间对您正确调用该方法进行单元测试)。使用活动时,您的活动是演示view.setPresenter(this)
者,您可能会调用start
and view.setPresenter(null)
; 这样,您就可以与多个演示者共享一个单例视图(但显然,一次最多只能有一个)。onStop
onCancel
单元测试方面,这真的没关系。如果你设计得当,这只是你需要在哪里注入存根(或模拟)的问题。不应允许单元测试决定设计决策。但是,单元测试通常会指出设计是否错误(例如缺少注入等)