Тестирование для поля класса с разделением между методами

#java #mocking #mockito #powermockito

Вопрос:

У меня есть класс Java, как показано ниже

 public class MyClass {
    private final ShowFactory showFactory;
    private SomeShow someShow;

    public MyClass(ShowFactory showFactory) {
        this.showFactory = showFactory;
        startShow();
    }

    public void startShow() {
        someShow = showFactory.createShow();
        someShow.start();
    }

    public void showSomething() {
        MagicBox magicBox = new MagicBox();
        someShow.showSomething(magicBox);
    }

    public void stopShow() {
        someShow.stop();
    }
}
 

и пытаюсь протестировать showSomething метод. Полный тестовый файл выглядит следующим образом

 public class MyClassTest {
    private ShowFactory showFactory;
    private SomeShow someShow;

    @Before
    public void setUp() {
        showFactory = mock(ShowFactory.class);
        someShow = mock(SomeShow.class);

        when(showFactory.createShow()).thenReturn(someShow);
    }

    @Test
    public void shouldStartShow() {
        new MyClass(showFactory);

        verify(someShow).start();
    }

    @Test
    public void shouldShowSomething() throws Exception {
        MagicBox magicBox = mock(MagicBox.class);
        PowerMockito.whenNew(MagicBox.class).withAnyArguments().thenReturn(magicBox);
        doNothing().when(someShow).showSomething(magicBox);
        InOrder inOrder = inOrder(someShow);

        MyClass myClass = new MyClass(showFactory);
        myClass.showSomething();

        inOrder.verify(someShow).start();
        inOrder.verify(someShow).showSomething(magicBox);
    }

    @Test
    public void shouldStopShow() {
        MyClass myClass = new MyClass(showFactory);
        myClass.stopShow();

        verify(someShow).start();
        verify(someShow).stop();
    }
}
 

Но тест shouldShowSomething проваливается с ошибкой Wanted but not invoked . Чего — нибудь мне здесь не хватает? Есть какие-нибудь предложения?

Комментарии:

1. Я думаю, вам нужно еще несколько шагов, чтобы использовать PowerMockito.whenNew их для моделирования вызова конструктора github.com/powermock/powermock/wiki/… Поэтому его нужно запустить с помощью PowerMockRunner и использовать @PrepareForTest с нужным классом в нем. Издевательство над внутренними компонентами метода вплоть до вызова конструктора довольно глубоко. Не могли бы вы поочередно использовать сопоставители, чтобы утверждать, что magicBox он находится в желаемом состоянии? Нравится inOrder.verify(someShow).showSomething(argThat(argument -> matchingLogicGoesHere)); .

Ответ №1:

Это было простое решение. После прочтения https://github.com/powermock/powermock/wiki/MockConstructor#quick-summary (спасибо @roby) оказывается, мне не хватало @PrepareForTest аннотации для класса.

 @RunWith(PowerMockRunner.class)
@PrepareForTest(MyClass.class)
public class MyClassTest {
 ...
}