Это работает как задумано.Однако вы можете настроить макеты вручную и вставить их в конструктор ConnectionManagementControllerImplTest
(перед вызовом setTestClass(...)
):
public ConnectionManagementControllerImplTest() {
super();
connectionManagementBusinessServiceMocked = Mockito.mock(ConnectionManagementBusinessService.class);
connectionManagementControllerMocked = new ConnectionManagementControllerImpl();
connectionManagementControllerMocked.setConnectionManagementBusinessService(connectionManagementBusinessServiceMocked);
setTestClass(ConnectionManagementControllerImpl.class, connectionManagementControllerMocked);
}
Не забудьте удалить аннотации @Mock
и @InjectMocks
.Кстати, вы даже можете удалить @RunWith(MockitoJUnitRunner.class)
в этом случае.
ОБНОВЛЕНИЕ: И конструктор класса теста, и метод "init", помеченные @Before
, выполняются для каждого теста.Разница в том, что аннотации Mockito обрабатываются между вызовами методов конструктора и @Before
.
Таким образом, вы можете немного изменить свой код для достижения положительного результата:
- Создайте метод "init" (помеченный
@Before
) внутри ConnectionManagementControllerImplTest
и переместите setTestClass()
в него из конструктора (в этом конкретном случае вы также можете удалить весь конструктор, потому что он будет содержать только super()
вызов). - Добавить
super.init()
после setTestClass()
строки (в противном случае метод "init"в родительском классе будет игнорироваться JUnit). - (Необязательно) вы также можете удалить аннотацию
@Before
из метода "init" в родительском классе, если ваши тесты написаны таким же образом.
Пример кода, реорганизованного таким образом:
public abstract class AbstractBaseTest<C> {
public MockMvc mockMvc;
private Class<C> clazz;
private Object inject;
protected abstract String getURL();
protected final void setTestClass(final Class<C> classToSet, final Object injectToSet) {
clazz = Preconditions.checkNotNull(classToSet);
inject = Preconditions.checkNotNull(injectToSet);
}
@Before //this annotation can be removed
public void init() throws Exception {
MockitoAnnotations.initMocks(clazz); //this line also can be removed because MockitoJUnitRunner does it for you
mockMvc = MockMvcBuilders.standaloneSetup(inject).build();
}
protected MockHttpServletResponse getResponse(MediaType produces) throws Exception {
MockHttpServletResponse response = mockMvc.perform(
get(getURL()).
accept(produces)).
andReturn().
getResponse();
return response;
}
protected MockHttpServletResponse postResponse(String content , MediaType consumes , MediaType produces) throws Exception {
MockHttpServletResponse response = mockMvc.perform(
post(getURL()).
content(content).
contentType(consumes).
accept(produces)).
andReturn().
getResponse();
return response;
}
}
@RunWith(MockitoJUnitRunner.class)
public class ConnectionManagementControllerImplTest extends AbstractBaseTest<ConnectionManagementControllerImpl> {
@Mock
private ConnectionManagementBusinessService connectionManagementBusinessServiceMocked;
@InjectMocks
private ConnectionManagementControllerImpl connectionManagementControllerMocked;
//constructor can be removed
public ConnectionManagementControllerImplTest() {
super();
}
@Before
public void init() throws Exception {
setTestClass(ConnectionManagementControllerImpl.class, connectionManagementControllerMocked);
super.init();
}
@Test
public void countConnectionsByInterval() throws Exception {
// given
given(connectionManagementBusinessServiceMocked.countConnectionsByInterval(Mockito.anyString()))
.willReturn(new ArrayList<ConnectionsCountDto>());
// when
MockHttpServletResponse response = postResponse("day", MediaType.TEXT_PLAIN, MediaType.APPLICATION_JSON_UTF8);
// then
assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
}
@Override
protected String getURL() {
return "/management/countConnectionsByInterval";
}
}
PS Я бы предпочел первый подход, но если вы не хотите иметь установщик для ConnectionManagementBusinessService
, вы можете выбрать последнее.Я проверил их обоих, и результат был одинаковым.