Подтвердить что ты не робот

Как я могу издеваться над методами класса @InjectMocks?

Например, у меня есть обработчик:

@Component
public class MyHandler {

  @AutoWired
  private MyDependency myDependency;

  public int someMethod() {
    ...
    return anotherMethod();
  }

  public int anotherMethod() {...}
}

чтобы проверить его, я хочу написать что-то вроде этого:

@RunWith(MockitoJUnitRunner.class}
class MyHandlerTest {

  @InjectMocks
  private MyHandler myHandler;

  @Mock
  private MyDependency myDependency;

  @Test
  public void testSomeMethod() {
    when(myHandler.anotherMethod()).thenReturn(1);
    assertEquals(myHandler.someMethod() == 1);
  }
}

Но он на самом деле называет anotherMethod() всякий раз, когда я пытаюсь его высмеять. Что делать с myHandler, чтобы издеваться над его методами?

4b9b3361

Ответ 1

Прежде всего, причина для издевательских методов MyHandler может быть следующей: мы уже тестировали anotherMethod() и у нее сложная логика, поэтому зачем нам ее снова тестировать (например, часть someMethod()), если мы можем просто verify, что он звонит?
Мы можем сделать это через:

@RunWith(MockitoJUnitRunner.class}
class MyHandlerTest {

  @Spy  
  @InjectMocks  
  private MyHandler myHandler;  

  @Mock  
  private MyDependency myDependency;  

  @Test  
  public void testSomeMethod() {  
    doReturn(1).when(myHandler).anotherMethod();  
    assertEquals(myHandler.someMethod() == 1);  
    verify(myHandler, times(1)).anotherMethod();  
  }  
}  

Примечание: в случае объекта "шпионаж" нам нужно использовать doReturn вместо thenReturn (небольшое объяснение здесь)

Ответ 2

В вашем коде вы вообще не тестируете MyHandler. Вы не хотите издеваться над тем, что вы тестируете, вы хотите назвать его фактические методы. Если у MyHandler есть зависимости, вы издеваетесь над ними.

Что-то вроде этого:

public interface MyDependency {
  public int otherMethod();
}

public class MyHandler {
  @AutoWired
  private MyDependency myDependency;

  public void someMethod() {
    myDependency.otherMethod();
  }
}

И в тесте:

private MyDependency mockDependency;
private MyHandler realHandler;

@Before
public void setup() {
   mockDependency = Mockito.mock(MyDependency.class);
   realHandler = new MyHandler();
   realhandler.setDependency(mockDependency); //but you might Springify this 
}

@Test
public void testSomeMethod() {

  //specify behaviour of mock
  when(mockDependency.otherMethod()).thenReturn(1);

  //really call the method under test
  realHandler.someMethod();
}

Суть в том, чтобы действительно вызвать тестируемый метод, но высмеять любые зависимости, которые они могут иметь (например, метод вызова других классов)

Если эти другие классы являются частью вашего приложения, тогда у них будут свои собственные модульные тесты.

ПРИМЕЧАНИЕ приведенный выше код может быть сокращен с помощью дополнительных комментариев, но я хотел бы сделать его более явным для объяснения (а также не могу вспомнить, что представляют собой аннотации:))