5

我有一个 java swing 应用程序,它希望用户选择YESNO从中选择JOptionPane.showConfirmDialog

由于 JOptionPane 停止线程并等待用户输入,因此我的代码无法自动测试。

无论如何我可以以编程方式解决这个问题吗?或模拟是或否?

在我现在的测试中,会出现一个确认对话框,我必须在其中按下是或否按钮。

更新

我找到了一个绝妙的选择。

我创建了一个接口,调用OptionPane了我需要的所有不同类型的消息。然后我创建了一个默认实现,它只归入 JOptionPane 的静态方法。然后我创建了一个 YesMockOptionPane,它基本上为所有确认消息返回 YES_OPTION,为所有 NO_OPTIONS 返回一个 NoMockOptionPane。

这是代码:

<<usage>>

class Foo {
  OptionPane optionPane = new DefaultOptionPane();

  public void someMethod() {
    if (optionPane.showConfirmDialog(null, "choose yes or no", "Please confirm", 
                    JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION)
                return;

        //User pressed yes
  }    

  public void setOptionPane(OptionPane o) {
    this.optionPane = o;
  }
}

//Snippet of the interface
public interface OptionPane {

   int showConfirmDialog(Component parentComponent,
          Object message, String title, int optionType);
}

public class DefaultOptionPane implements OptionPane {
  @Override
  public int showConfirmDialog(Component parentComponent,
        Object message, String title, int optionType) {

      return JOptionPane.showConfirmDialog(parentComponent,message,title,optionType);
  }
}

public class YesMockOptionPane extends DefaultOptionPane {
  //MockOptionPane is just an abstract class implementing default methods from OptionPane
  @Override
  public int showConfirmDialog(Component parentComponent, Object message, String title, int optionType) {
      return JOptionPane.YES_OPTION;
   }
}

现在在单元测试中我可以简单地设置适当的 MockOptionPane。

dialog.setOptionPane(new YesMockOptionPane());
4

3 回答 3

3

优雅的方法是修改代码以期望来自界面的答案,例如

public interface UserAnswer {
    boolean yesPressed();
}

然后使用 JOptionPane.showConfirmDialog 为生产代码实现它,并为测试代码硬编码。

如果这不可行,您可以尝试使用 EventQueue.invokeLater 将事件分派线程上的事件发送到 JOptionPane。

于 2012-07-17T12:43:22.303 回答
3

这是我想出的解决方案(也在问题中复制)

<<usage>>

class Foo {
  OptionPane optionPane = new DefaultOptionPane();

  public void someMethod() {
    if (optionPane.showConfirmDialog(null, "choose yes or no", "Please confirm", 
                    JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION)
                return;

        //User pressed yes
  }    

  public void setOptionPane(OptionPane o) {
    this.optionPane = o;
  }
}

//Snippet of the interface
public interface OptionPane {

   int showConfirmDialog(Component parentComponent,
          Object message, String title, int optionType);
}

public class DefaultOptionPane implements OptionPane {
  @Override
  public int showConfirmDialog(Component parentComponent,
        Object message, String title, int optionType) {

      return JOptionPane.showConfirmDialog(parentComponent,message,title,optionType);
  }
}

public class YesMockOptionPane extends MockOptionPane {

  @Override
  public int showConfirmDialog(Component parentComponent, Object message, String title, int optionType) {
      return JOptionPane.YES_OPTION;
   }
}

现在在单元测试中我可以简单地设置适当的 MockOptionPane。

dialog.setOptionPane(new YesMockOptionPane());
于 2012-07-17T13:04:08.593 回答
1

我认为对此会有现有的答案,但我找不到任何答案!

我认为您需要在代码和 JOptionPane 之间创建一个抽象层。
这应该是带有方法的接口的形式,无论用户是否选择了“是”或“否”,该方法都将返回您的代码 - 您可以将该方法调用一些有意义的东西,例如“isWantToOverwriteExistingFile”或类似的东西。

该接口的正常实现会像您现在所做的那样调用您的 JOptionPane。
您的测试将使用此接口的不同实现,这将根据您希望测试做出的选择返回是或否(不显示 JOptionPane)。

如果您需要更多详细信息,请告诉我!

于 2012-07-17T12:44:00.933 回答