在MVP GWT应用程序中测试Presenter

9

我有一个简单的应用程序,想要使其可测试。我在这个领域是新手。 这里有一个简单的Presenter,考虑到这段代码,你能否给我一些建议或示例如何测试它。

    public class SomePresenter extends Presenter<MainPanelPresenter.Display>
    {

    public interface Display extends WidgetDisplay
    {
      HasClickHandlers getAddButton();

      HasClickHandlers getDeleteButton();

      void setData(ArrayList<Person> data);

      ArrayList<String> getSelectedRows();

      Widget asWidget();

    }

    private final DispatchAsync dispatcher;
    public static final Place PLACE = new Place("main");

    @Inject
    public SomePresenter(DispatchAsync dispatcher, EventBus eventBus, Display display)
    {
      super(display, eventBus);
      this.dispatcher = dispatcher;
      bind();
    }

    protected void onBind()
    {
      display.getAddButton().addClickHandler(new ClickHandler()
      {
        public void onClick(ClickEvent event)
        {
          eventBus.fireEvent(new AddButtonEvent());
        }
      });

      display.getDeleteButton().addClickHandler(new ClickHandler()
      {
        public void onClick(ClickEvent event)
        {
          ArrayList<String> list = display.getSelectedRows();
          deletePerson(list);
        }
      });
    }
    ....
    private void loadDbData()
    {
     ..........
    }
    private void deletePerson(ArrayList<String> ids)
    {
     ..........
     }
   }

编辑:

Presenter是什么,它从数据库中加载初始数据,并有两个按钮添加和删除。 当按下添加按钮时,会加载一个新的表单,用户可以输入数据并保存到数据库中, 删除按钮只是从数据库中删除人员。

谢谢

1个回答

5

对于这样的类进行单元测试的一般想法与其他类相同:

  • 创建依赖项的模拟版本(如Display、EventBus等)
  • 设置期望,指示Presenter工作时依赖项应该执行的操作
  • 运行Presenter并检查期望结果

然而,您的Presenter版本存在一些问题:

  • loadDbData()方法未显示,但我假设它意味着Presenter也可以访问某些其他组件以进行获取。是否可以将此组件抽象为依赖项,并像其他部分一样进行模拟?

  • 然后是bind()的测试。在此方法中,您的Presenter的唯一责任是在Display提供的某些按钮上设置回调。要测试的内容包括:

    • 回调已设置
    • 设置的回调执行了预期的操作

以下是几个有助于解决后一个问题的想法:

您可以减少Presenter和Button之间的耦合。如果可能,将Display接口从以下形式更改:

Button getAddButton();

to

addAddButtonClickedHandler(ClickHandler);

这意味着您的Presenter不必使用返回实际按钮的Display对象。您可以将回调内容减少到调用单个方法,然后可以在隔离中进行测试。
protected void bind() {
   display.addAddButtonClickHandler(new ClickHandler() {
       public void onClick(ClickEvent) {
          fireAdded();
       } 
   });
} 

// The fireAdded function can be tested independenty of the Display, potentially with 
// a mock EventBus
protected void fireAdded() {
   event.fireEvent(....)
}

如果你真的想检查回调函数是否正确设置,那么你可以使用“Dummy”实现 Display 类。该实现提供了所有回调函数的列表,并允许你调用它们。

private class DummyDisplay implements Display  {

   private List<ClickHandler> addButtonClickHandlers;
   public void addAddButtonClickHandler(ClickHandler handler) {
       addButtonClickHandlers.add(handler);
   }
   public void fireAddButtonClick() {
       for (ClickHandler h in addButtonClickHandlers) {
              h.onClick(new ClickEvent());
       }
   }
   // .... 
}

那么你的测试应该:
  • 创建一个具有虚拟显示的presenter
  • 使用bind设置回调函数
  • 使用display.fireAddButtonClick()模拟用户点击
  • 检查是否已经看到了点击结果,fireAdded的影响
这种类(大多数情况下将其他类粘合在一起)往往很难测试;在某些情况下,如果其他类得到了彻底的测试,集中精力于粘合剂而不是被粘合的部分可能会变得有点低效。
希望这可以帮助你。

如果ClickEvent有受保护的构造函数,那么实例化它对你有什么影响? - dzieciou
这只是一个例子,我不知道确切的ClickHandler类(我假设它只是一个接口)。 - phtrivier
ClickEvent是GWT库的一个类,按照你所建议的方式构造它将导致编译时失败。这个答案采用了另一种方法来验证Presenter是否可以正确地从View中分派事件。 - dzieciou

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接