Java 在MVP GWT应用程序中测试演示者

Java 在MVP GWT应用程序中测试演示者,java,unit-testing,gwt,mvp,Java,Unit Testing,Gwt,Mvp,我有一个简单的应用程序,并希望使其可测试。我是这方面的新手。 下面是一个简单的演示者,请记住这段代码,您能给我一些建议或给我一些如何测试它的示例吗 public class SomePresenter extends Presenter<MainPanelPresenter.Display> { public interface Display extends WidgetDisplay { HasClickHandlers getAdd

我有一个简单的应用程序,并希望使其可测试。我是这方面的新手。 下面是一个简单的演示者,请记住这段代码,您能给我一些建议或给我一些如何测试它的示例吗

    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)
    {
     ..........
     }
   }
公共类SomePresenter扩展Presenter
{
公共界面显示扩展了WidgetDisplay
{
HasClickHandlers getAddButton();
HasClickHandlers getDeleteButton();
void setData(数组列表数据);
ArrayList getSelectedRows();
Widget asWidget();
}
专用最终调度异步调度;
公共静态最终地点=新地点(“主要”);
@注入
公共SomePresenter(DispatchAsync dispatcher、EventBus、EventBus、Display)
{
超级(显示、事件总线);
this.dispatcher=dispatcher;
bind();
}
受保护的void onBind()
{
display.getAddButton().addClickHandler(新建ClickHandler())
{
公共作废一次点击(点击事件)
{
fireEvent(新的AddButtonEvent());
}
});
display.getDeleteButton().addClickHandler(新建ClickHandler())
{
公共作废一次点击(点击事件)
{
ArrayList=display.getSelectedRows();
删除人(名单);
}
});
}
....
私有void loadDbData()
{
..........
}
私有void deletePerson(ArrayList ID)
{
..........
}
}
编辑:

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


谢谢

单元测试的一般思想是这样一个类,就像任何其他类一样:

  • 创建依赖项的模拟版本(显示、事件总线等)
  • 设定演示者工作时部门应做什么的期望
  • 练习演讲者并检查期望值
但是,您的演示者版本存在几个问题:

  • loadDbData()方法没有显示,但我认为这意味着演示者还可以访问执行抓取的其他组件。这个组件可以在依赖项中被删除,并像其他组件一样被模拟吗

  • 然后是bind()的测试。在此方法中,演示者的唯一职责是对显示器提供的某些按钮设置回调。您要测试的内容包括:

    • 已设置回调
    • set回调实现了预期的功能
以下几点有助于后面的工作:

您可以减少演示者和按钮之间的耦合。如果可能,将显示界面更改为:

Button getAddButton();

这意味着您的演示者不必使用返回实际按钮的显示对象

您可以将回调内容减少为调用单个方法,然后可以单独进行测试

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(....)
}
如果您确实想检查回调是否正确设置,那么可以使用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());
       }
   }
   // .... 
}
私有类DummyDisplay实现显示{
私有列表addButtonClickhandler;
public void addButtonClickhandler(单击处理程序){
addButtonClickHandlers.add(处理程序);
}
公共无效fireAddButtonClick(){
对于(addButtonClickHandlers中的ClickHandler h){
h、 onClick(新建ClickEvent());
}
}
// .... 
}
那么您的测试将:

  • 创建具有此类虚拟显示的演示者
  • 使用bind设置回调
  • 使用display.fireAddButtonClick()模拟用户单击
  • 检查是否有单击的结果,可以看到fireAdded的效果
这种类型的类(主要是将其他类粘合在一起)往往很难测试;在某一点上,如果其他类都经过了彻底的测试,那么将注意力集中在胶水上,而不是胶水上,可能会产生轻微的反效果


希望这有帮助

如果
ClickEvent
保护了构造函数,那么它的实例化是如何为您工作的?这只是一个例子,我不知道确切的ClickHandler类(我假设它只是一个接口)。
ClickEvent
是一个类,是GWT库的一部分,按照您的建议构造它将导致您的解决方案在编译过程中失败。这采用了另一种方法来验证演示者是否可以从视图中正确分派事件。
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());
       }
   }
   // .... 
}