Когда я использую @WebMvcTest
для тестирования моего Spring Controller, у меня возникают два вопроса:
- MockMvc не может найти правильный URL-адрес
- После добавления
MockMvcBuilders.standaloneSetup()
, mockMvcсработал. Но мой контроллер throw NullPointException caused by @Autowired Service
Я просто выполняю модульное тестирование, поэтому я не хочу использовать @SpringBootTest
для запуска всех приложений SpringBoot. Я попытался @InjectMock
Мой контроллер и @Mock or @MockBean
Сервис. Все они не работали. Так может кто-нибудь сказать мне, почему @Autowired
mockMvc не может найти контроллер и как имитировать внутреннюю @Autowired
, поданную в модульном тесте Спока без @SpringBootTest
?
Вот мой контроллер
@RestController
@RequestMapping("/schedule/filter")
public class ScheduleObjectFilterController extends BaseController {
@PostMapping(path="/",produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public String createScheduleObjectFilter(@RequestBody String body){
BaseResponse<ResponseStatus> resp = new BaseResponse<>(ResponseStatus._200);
try{
List<ScheduleObjectFilterParam> paramList = parseJSONArray(body,ScheduleObjectFilterParam.class);
resp.setStatus(scheduleObjectFilterService.createScheduleObjectFilter(paramList));
}catch(BaseRuntimeException e){
logger.error("Create ScheduleObjectFilter error:", e);
resp.setException(e);
}catch(Exception e){
logger.error("Create ScheduleObjectFilter error:", e);
resp.setStatus(ResponseStatus._500);
}
return renderJSON(resp);
}
@Autowired
private ScheduleObjectFilterService scheduleObjectFilterService;
}
Вот мой Сервис и его реализация
public interface ScheduleObjectFilterService{
ResponseStatus createScheduleObjectFilter(List<ScheduleObjectFilterParam> paramList);
}
@Service
public class ScheduleObjectFilterServiceImpl extends BaseService implements ScheduleObjectFilterService {
public ResponseStatus createScheduleObjectFilter(List<ScheduleObjectFilterParam> paramList) {
// some code
}
}
Вот мой тестовый класс
@WebMvcTest(controllers = [ScheduleObjectFilterController.class])
@ActiveProfiles("local")
class ScheduleSettingControllerSpecification extends Specification{
@Autowired
MockMvc mockMvc
@MockBean
BaseController baseController
@MockBean
ScheduleObjectFilterService scheduleObjectFilterService
def setup(){
//after add next line,the mockMvc can find url,but service throw NullPointException
//mockMvc = MockMvcBuilders.standaloneSetup(new ScheduleObjectFilterController()).build()
scheduleObjectFilterService.createScheduleObjectFilter(_ as List) >> ResponseStatus._500
}
def "MvcTest"(){
given:
ScheduleObjectFilterParam param = new ScheduleObjectFilterParam()
List<ScheduleObjectFilterParam> dataList = Collections.singletonList(param)
expect:
mockMvc.perform(post("/schedule/filter/").contentType(MediaType.APPLICATION_JSON).content(JSONObject.toJSONString(dataList)))
.andExpect(status().isOk())
}
}
перед добавлением MockMvcBuilders.standaloneSetup()
:
MockHttpServletRequest:
HTTP Method = POST
Request URI = /schedule/filter/
Parameters = {}
Headers = {Content-Type=[application/json]}
Body = <no character encoding set>
Session Attrs = {}
Handler:
Type = org.springframework.web.servlet.resource.ResourceHttpRequestHandler
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 404
Error message = null
Headers = {}
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
После добавления То:
2019-11-10 11:53:22.896 [WEB] [ERROR] com.kaifa.hes.schedule.controller.ScheduleObjectFilterController.createScheduleObjectFilter() -> Create ScheduleObjectFilter error:
java.lang.NullPointerException: null
at com.kaifa.hes.schedule.controller.ScheduleObjectFilterController.createScheduleObjectFilter(ScheduleObjectFilterController.java:47) [classes/:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_201]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_201]
......
это исключение прямо на эту строку в контроллере
resp.setStatus(scheduleObjectFilterService.createScheduleObjectFilter(paramList));