Используя Guice, как я могу ввести фиктивный объект из моего модульного теста в тестируемый класс
Рассмотрим следующий код:
@Singleton
public class MyServiceImpl {
public int doSomething() {
return 5;
}
}
@ImplementedBy(MyServiceImpl.class)
public interface MyService {
public int doSomething();
}
public class MyCommand {
@Inject private MyService service;
public boolean executeSomething() {
return service.doSomething() > 0;
}
}
public class MyCommandTest {
@InjectMocks MyServiceImpl serviceMock;
private MyCommand command;
@Before public void beforeEach() {
MockitoAnnotations.initMocks(this);
command = new MyCommand();
when(serviceMock.doSomething()).thenReturn(-1); // <- Error here
}
@Test public void mockInjected() {
boolean result = command.executeSomething();
verify(serviceMock).doSomething();
assertThat(result, equalTo(false));
}
}
Мой тест падает, когда я пытаюсь заглушить метод doSomething() в моем фиктивном объекте реализации. Я получаю ошибку:
org.mockito.exceptions.misusing.MissingMethodInvocationException: when () требует аргумент, который должен быть "вызовом метода для макета". Например: when (mock.getArticles ()). ThenReturn (Articles);
Кроме того, эта ошибка может появиться, потому что: 1. вы заглушаете любой из методов: final/private/equals()/hashCode(). Эти методы не могут быть проверены. Методы насмешек, объявленные в закрытых родительских классах, не поддерживаются. 2. внутри when () вы вызываете не метод на макете, а на каком-то другом объекте.
Я новичок в внедрении зависимостей через Guice, и я не уверен, почему я не могу издеваться над объектом реализации таким образом?
1 ответ
Тест без CDI
Простое решение - объединить CDI с Constructor Injection и забыть о Guice для теста:
public class MyCommand {
private final MyService service;
@Inject
public MyCommand(MyService service) {
this.service = service;
}
public boolean executeSomething() {
return service.doSomething() > 0;
}
}
@RunWith(MockitoJUnitRunner.class)
public class MyCommandTest {
@Mock
MyServiceImpl serviceMock;
private MyCommand command;
@Before public void beforeEach() {
MockitoAnnotations.initMocks(this);
when(serviceMock.doSomething()).thenReturn(-1); // <- Error here
// inject without Guice
command = new MyCommand(serviceMock);
}
}
Тест с Мокито, делающим CDI
Иначе, если вам не нравится Constructor Injection, тестовый код должен выглядеть так:
@RunWith(MockitoJUnitRunner.class)
public class MyCommandTest {
@Mock
MyServiceImpl serviceMock;
@InjectMocks
private MyCommand command;
@Before
public void beforeEach() {
MockitoAnnotations.initMocks(this);
command = new MyCommand();
when(serviceMock.doSomething()).thenReturn(-1); // <- Error here
}
}