从单元测试的角度来看:在 GWT MVP 中,视图应该指定 Presenter 还是相反?

发布于 2024-11-04 03:57:37 字数 343 浏览 5 评论 0原文

在 GWT 教程中,Google 使用不同的方法来实现 MVP,要么 View 指定 Presenter,要么 Presenter 指定 View。第一个在使用“活动”和“地点”时使用。

这篇文章涉及这个主题:MVP:应该View 实现 Presenter 的接口还是反之亦然?

但是,我想知道在对 Presenter 和视图进行单元测试时,您认为哪种替代方案最好?或者两者都会同样有效吗?

In tutorials on GWT Google uses to different approaches to do MVP, either the View specifies the Presenter or the Presenter specifies the View. The first one is used when using Activities and Places.

This post touches on this subject: MVP: Should the View implement a Presenter's interface or vice versa?

However I would like to know which alternative you think is best when it comes to unit testing of the presenter and the view? Or will both work equally well?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

岁月无声 2024-11-11 03:57:37

Presenter 单元测试背后的想法是模拟视图,并针对该模拟视图的状态编写几个断言,这些断言将在现实生活应用程序中直观地表示。由于采用了这种方法,因此无需运行完整的 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 的事情变得更容易。

The idea behind unit testing of presenter is to mock the view, and write several assertions against state of this mocked view, which would be represented visually in the real life app. Thanks to such an approach there is no need for running full GWTTestCase, which takes a lot of time and should be rather put in the category of integration testing, not unit testing.

If you would try both MVP approaches, the unit tests could look like:

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));
}

Where the MockButton is something I described here:
Comprehensive Pros/Cons of Mocking Frameworks for GWT

Although possible, it is not really convenient to mock things this way. The MVP2 approach seems to perform better:

@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));
}

Another reason for using the second approach is the problem in MVP1 with declaring elements of the display, which would trigger different events (e.g. ClickEvent, FocusEvent). MVP2 also makes things easier when it comes to UiBinder.

思念满溢 2024-11-11 03:57:37

避免使用 HasXxxHandlers,即使用 中的方法第 2 部分 文章中每个对等点都互相引用。 HasXxxHandlers 太复杂而无法模拟,特别是在使用 Mockito 或 EasyMock 等模拟库时。
为了获得最佳的可测试性,您可以将视图注入演示者,然后演示者将调用视图的 setPresentersetDelegate 方法(这样,您就可以对其进行单元测试)您在正确的时间正确地调用了该方法)。使用 Activity 时,如果您的 Activity 是演示者,您可能会在 startview.setPresenter(null) 中调用 view.setPresenter(this) onStoponCancel 中的 code>;这样,您就可以与多个演示者共享一个单例视图(显然,一次最多只能有一个)。

Avoid using HasXxxHandlers, i.e. use the approach from the part 2 article where each peer has a reference to the other. HasXxxHandlers are far too complicated to mock, particularly when using mocking libraries such as Mockito or EasyMock.
For best testability, you'd inject the view into the presenter and the presenter would then call a setPresenter or setDelegate method of the view (that way, you can unit test that you correctly call that method, at the right time). When using Activities, where your activity is a presenter, you'll likely call view.setPresenter(this) in start and view.setPresenter(null) in onStop and onCancel; that way you can have a singleton view shared with several presenters (though no more than a single one at a time, obviously).

恬淡成诗 2024-11-11 03:57:37

就单元测试而言,这确实不重要。如果你设计得正确,那么问题就在于你需要在哪里注入存根(或模拟)。单元测试不应该被允许决定设计决策。然而,单元测试通常会表明设计是否错误(例如缺少注入等)。

Unit-test-wise, it really doesn't matter. If you design it right, it is just a matter of where you need a stub (or mock) injected. The unit test should not be allowed to dictate design decisions. However, a unit-test will often indicate if a design is wrong (such as missing injection etc.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文