如何使用Java Swing JOptionPane确认对话框进行单元测试

时间:2012-07-17 12:31:17

标签: java swing unit-testing joptionpane

我有一个java swing应用程序,希望用户从YES

中选择NOJOptionPane.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());

3 个答案:

答案 0 :(得分:3)

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

public interface UserAnswer {
    boolean yesPressed();
}

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

如果无法做到这一点,您可以尝试使用EventQueue.invokeLater将事件发送线程上的事件发送到JOptionPane。

答案 1 :(得分: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());

答案 2 :(得分:1)

我以为会有现成的答案,但我找不到任何答案!

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

这个界面的正常实现会像你现在所做的那样调用你的JOptionPane 您的测试将使用此接口的不同实现,它将返回yes或no(不显示JOptionPane),具体取决于您希望测试的选择。

如果您需要更多详细信息,请与我们联系!