смущен модульным тестированием и Mockito

1

Я новичок в модульном тестировании и Mockito. Я смутился тем, что я должен проверить и проверить. У меня класс А следующим образом:

public class A{
    @Autowired
    private B b;

    public double doSomething(Request r){
        r = b.process1(r);
        r = b.process2(r);
        return calculateFinal(r);
    }

    public void reportSomething(Request r){
        r = b.process1(r);
        r = b.process2(r);
        b.report(r);
    }

    private int calculateFinal(Request r){
        return r.getFinalScore() * 2;
    }
}

Предположим, я хочу протестировать эти два метода с помощью теста Junit. Поскольку у меня есть зависимость B в A, я издеваюсь над ней с Mockito. Для обоих тестов мне сказали, что я должен предположить, что зависимость b полностью протестирована и правильно работает, так как мы хотим проверить бизнес-логику в A.

Сначала мне кажется, что мне не нужно ничего тестировать для reportSomething() поскольку он включает только вызовы b и все они "работают"? Единственное, что я могу придумать, чтобы проверить, действительно ли они вызваны и порядок вызовов, правильно? Так что я должен просто вызвать a.reportSomething(), а затем выполнить проверку? Одна вещь, которая меня беспокоит, заключается в том, должен ли я заглушить b.process1() и b.process2(), чтобы вернуть что-либо. Я пробовал ничего не делать, и это сработало, но почему?

Для testDoSomething() я думаю, что я действительно тестирую метод calculateFinal(). Но поскольку он использует данные из объекта Request, мне нужно сначала установить эти данные в запросе r. Поскольку r непосредственно поступает из b.process2(), я должен b.process2() вызов метода, чтобы вернуть объект Request с b.process2() данными. Но я мог бы пропустить b.process1(), правильно?

Это правильный процесс мышления? Я что-то пропустил или что-то не понял? Если это так, есть ли лучший и более чистый способ написать его? Спасибо!

public class ATest{
    private static final int SCORE = 100;

    @Mock
    private B mockB;

    @InjectMocks
    private A aClient;

    @Before
    public void setUpTest{
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void testReportSomething(){
        // what should I test here?

        Request r = new Request();

        // is it necessary to include the following two lines?
        when(mockB.process1(any(Request.class))).return(r);
        when(mockB.process2(any(Request.class))).return(r);


        aClient.reportSomething(r);
        InOrder inOrder = inOrder(mockProcesser);
        inOrder.verify(mockProcesser).process1(any(Request.class));
        inOrder.verify(mockProcesser).process2(any(Request.class));
        inOrder.verify(mockProcesser).report(any(Request.class));
    }

    @Test
    public void testDoSomething(){
        // Is this correct?
        Request r = new Request();
        r.setFinal(SCORE);

        // I skipped this line and it still works
        when(mockB.process1(any(Request.class))).return(r);

        when(mockB.process2(any(Request.class))).return(r);
        assert(SCORE * 2, aClient.doSomething(r));
        // is it still necessary to verify the call to mockB?
    }
}
Теги:
unit-testing
junit
mockito
mocking

1 ответ

2

Вы делаете свой тест неправильно. Давайте посмотрим на метод, который вы хотите проверить:

public void reportSomething(Request r){
    r = b.process1(r);
    r = b.process2(r);
    b.report(r);
}

Прежде всего, вам нужно высмеять это, когда b обрабатывает запрос, он возвращает ожидаемый результат; Поэтому НЕ используйте одно и то же возвращаемое значение для двух вызовов.

Вот как я бы написал тест:

final Request r = mock(Request.class);
final Request r1 = mock(Request.class);
final Request r2 = mock(Request.class);

when(mockB.process1(r)).thenReturn(r1);
when(mockB.process2(r1)).thenReturn(r2);
doNothing().when(mockB).report(any(Request.class));

final InOrder inOrder = inOrder(mockB);

// Launch... And then verify:

inOrder.verify(mockB).process1(r);
inOrder.verify(mockB).process2(r1);
inOrder.verify(mockB).report(r2);
inOrder.verifyNoMoreInteractions();

Относительно:

  // is it necessary to include the following two lines?

Да. По умолчанию, когда неопределенный, mocked экземпляр возвращает значения по умолчанию Java: 0 для числовых примитивов, false для boolean, null для объектов. Вы ДОЛЖНЫ указать, что вы хотите вернуть путем stubbing.

  • 0
    Таким образом, хотя мы знаем, что зависимость b работает должным образом, нам все равно нужно смоделировать ее словами «когда b обрабатывает запрос, он возвращает ожидаемый результат»? Кроме того, почему doNothing().when(mockB).report(any(Request.class)); но не doNothing().when(mockB).report(r2); ? Благодарю.
  • 0
    b может работать правильно, но здесь вы не тестируете b ; как и второй пункт, это расширение области заглушки. b.report() проверки, и вы хотите проверить, что b.report() был вызван с помощью r2 .
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню