Мне нужно протестировать контроллер, и для большинства деталей все еще достаточно использовать MockMvc
. Но есть еще несколько веток, для которых очень сложно создать контрольный пример. Поэтому я использую Mockito
для методов-заглушек и исключения для этого специального теста.
Мой контроллер реализует службу, и настройка выглядит следующим образом:
MyController.class :
@RestController
@RequestMapping("/myTest")
public class MyController {
@Autowired
private MyService myService;
@RequestMapping(value = "/", method = { RequestMethod.POST }, produces = "application/json")
public final int controllerMethod() {
return myService.serviceMethod();
}
}
MyService.class :
@Service
public class MyService {
@PreAuthorize("hasRole('ROLE_ADMIN')")
public int serviceMethod() {
return 5;
}
}
Поэтому у меня есть несколько методов тестирования, и в некоторых методах я высмеиваю MyService.class
, чтобы бросить исключение для примера. Но в других методах я хочу проверить нормальные функции. Так что здесь возникает проблема. Если тесты не выполняются в правильном порядке, нормальный тест на функциональность не будет работать, потому что, я думаю, MyService.class
все еще высмеивается. Таким образом, в этом примере serviceMethod возвращает null вместо 5.
Есть ли способ частично InjectMocks - так я имею в виду только для специальных методов, а не для класса?
Вот пример код:
MyControllerTest.class :
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = Config.class)
@WebAppConfiguration
public class MyControllerTest {
@Autowired
private WebApplicationContext webApplicationContext;
@Autowired
MyService myService;
@InjectMocks
@Resource
MyController myController;
@Resource
private FilterChainProxy springSecurityFilterChain;
private MockMvc mockMvc;
@Before
public void setup() throws SQLException {
this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).apply(springSecurity()).build();
}
@Test
@WithMockUser(username = "validUser", roles = { "ADMIN" })
public void testMyController() throws Exception {
mockMvc.perform(post("/myTest/").with(csrf())).andDo(print()).andExpect(status().is2xxSuccessful()).andExpect(jsonPath("$", is(5)));
}
@Test
@WithMockUser(username = "validUser", roles = { "ADMIN" })
public void testMyControllerException() throws Exception {
myService = Mockito.spy(MyService.class);
MockitoAnnotations.initMocks(this);
Mockito.doThrow(new IndexOutOfBoundsException()).when(myService).serviceMethod();
mockMvc.perform(post("/myTest/").with(csrf())).andDo(print()).andExpect(status().is4xxClientError());
Mockito.verify(myService, Mockito.times(1)).serviceMethod();
}
}
Так что, если я запускаю только один из этих тестов, оба работают хорошо. Но если я запускаю оба вместе, и testMyControllerException()
будет выполняться первым, testMyController()
завершится неудачно из-за поддельного экземпляра myService-Instance, я думаю.
Есть ли способ исправить эту проблему, или он должен Я разделил эти тесты на два разных тестовых класса?
Я пытался найти способ снять myController.class
с аннотации @After
с помощью Mockito.reset(myController);
. Но у меня не сработало.