Search code examples
javaswingunit-testingjoptionpane

How to unit test with Java Swing JOptionPane Confirm Dialog


I have a java swing application which expects the users to choose YES or NO from JOptionPane.showConfirmDialog

Since the JOptionPane stops the thread and is waiting for user input, my code is not automatically testable.

Is there anyway I can programatically get around this? Or simulate yes or no?

In my test now, a confirm dialog appears, where I have to push the yes or no button.

Update

I found a brilliant option.

I created an interface called OptionPane with basically all the different types of messages I need. Then I created a default implementation that just relegates to the JOptionPane`s static methods. Then I created a YesMockOptionPane, that basically returns YES_OPTION for all the confirm messages, and a NoMockOptionPane for all the NO_OPTIONS.

Here is the code:

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

Now in the unit test I can simply set the appropriate MockOptionPane.

dialog.setOptionPane(new YesMockOptionPane());

Solution

  • This is the solution I came up with (also copied in the question)

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

    Now in the unit test I can simply set the appropriate MockOptionPane.

    dialog.setOptionPane(new YesMockOptionPane());