How to apply unit tests when the main class is an interface?

-4

I have this method in my Beginning class

@Override
public void question() {
    String question = String.format(TEXT_OF_A_QUESTION, this.namePlate);
    int answer = JOptionPane.showConfirmDialog(null, question, "Question", JOptionPane.YES_NO_OPTION);

    if (Integer.valueOf(answer).equals(JOptionPane.YES_OPTION)) {
        this.positive.positiveAnswer();
    } else {
        this.negative.negativeAnswer(this);
    }
}

How do I create a unit test to test this method? I'm trying to get problems because my model is an interface as you can see below;

package com.test.wladimir.gamergourmet.model;

public interface Plate {

    String namePlate();

    void question();

    void questionLevel(String positiveAnswer, String negativeAnswer);

    void positiveAnswer();

    void negativeAnswer(Plate plate);
}

This is my APPLICATION

This was my attempt;

@RunWith(MockitoJUnitRunner.Silent.class)
public class BeginningTest {

    private static final String TEXT_OF_A_QUESTION = "O prato que você pensou é %s?";
    private static String namePlate = "torta";

    private Plate positive;
    private Plate negative;

    @Mock
    private Beginning beginningController;

    @Before
    public void setUp() {
        beginningController = new Beginning(namePlate);
    }

    @Test
    public void testQuestion() {

        String question = String.format(TEXT_OF_A_QUESTION, this.namePlate);
        assertThat(question, notNullValue());

    }

But I do not know if I'm right!

    
asked by anonymous 26.12.2018 / 22:03

1 answer

1

The first thing to understand is to know what you want to test .

In your code, you can test the following items:

  • Return from String.format to TEXT_OF_A_QUESTION
  • Condition within if

first difficulty to test your code is this JOptionPane.showConfirmDialog . You need to somehow put an interface in place and change its implementation in the test.

For example:

class Beginning {

    private OptionPane optionPane = new DefaultOptionPane();

    private String namePlate;
    private Plate positive;
    private Plate negative;

    @Override
    public void question() {
        String question = String.format(TEXT_OF_A_QUESTION, this.namePlate);
        int answer = optionPane.showConfirmDialog(null, question, "Question", JOptionPane.YES_NO_OPTION);

        if (Integer.valueOf(answer).equals(JOptionPane.YES_OPTION)) {
            this.positive.positiveAnswer();
        } else {
            this.negative.negativeAnswer(this);
        }
    }

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

}

And the implementation of the 2 classes you will need: one with the implementation for the application and another for the unit testing:

public class DefaultOptionPane implements OptionPane {

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

public class YesMockOptionPane implements OptionPane {

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

By default, your code will always use DefaultOptionPane , but in your test you can overwrite it via the setOptionPane method.

Next, you will basically need to override% mockite% methods to understand whether verify or positive is called, depending on the negative return. But their original code instantiates them internally, this is bad for mockar them, as they also need to expose them. You can do this by creating optionPane methods for them as well, although in practice they ideally were injected via constructor, hence you can use the same entry point to pass the mock classes.

I'm going to give the example using set itself. It would be something like this test:

@Test
public void test() throws Exception {

  OptionPane optionPane = mock(OptionPane.class);
  when(optionPane.showConfirmDialog(any(),any(),any(),any()).thenReturn(1); // 1 = Yes, eu acho...

  Pane negative = mock(Pane.class);
  Pane positive = mock(Pane.class);

  Beginning b = new Beginning ("lagosta");
  b.setOptionPane(optionPane);
  b.setNegative(negative);
  b.setPositive(positive);

  verify(positive, times(1)).positiveAnswer();
  verify(positive, times(0)).negativeAnswer(any());
}

I think you got the idea. The test of set can be done via mock, waiting for the desired result as the entry point of the String.format method, something like this:

when(optionPane.showConfirmDialog(any(),eq("O prato que você pensou é lagosta"),any(),any()).thenReturn(1);
    
27.12.2018 / 17:00