我有一个非常简单的RESTful控制器,可以使用并生成JSON。我需要脱机测试此控制器,即没有服务器运行,也没有数据库运行。而且我为无法找到解决方案而发疯。我的初始测试用例将包括:
断言将测试JSON数据 我有以下URI:
/ pcusers-返回所有用户
注意:这不是典型的MVC应用程序。我没有意见。我有一个纯REST控制器,它发出JSON并使用JSON格式的数据。
如果有人可以引导我朝正确的方向前进,将不胜感激。
只是为了清楚我的代码是什么样子:
@Controller @RequestMapping("/pcusers") public class PcUserController { protected static Logger logger = Logger.getLogger(PcUserController.class); @Resource(name = "pcUserService") private PcUserService pcUserService; @RequestMapping(value = "", method = RequestMethod.GET, produces = "application/json") @ResponseBody public List<PcUser> readAll() { logger.debug("Delegating to service to return all PcUsers"); return pcUserService.readAll(); } @RequestMapping(value = "/{id}", method = RequestMethod.GET, consumes = "application/json", produces = "application/json") @ResponseBody public PcUser read(@PathVariable String id) { logger.debug("Delegating to service to return PcUser " + id); return pcUserService.read(id); } @RequestMapping(value = "/create/{pcUser}", method = RequestMethod.POST, consumes = "application/json", produces = "application/json") @ResponseBody public boolean create(@PathVariable PcUser pcUser) { logger.debug("Delegating to service to create new PcUser"); return pcUserService.create(pcUser); } @RequestMapping(value = "/update/{pcUser}", method = RequestMethod.POST, consumes = "application/json", produces = "application/json") @ResponseBody public boolean update(@PathVariable PcUser pcUser) { logger.debug("Delegating to service to update existing PcUser"); return pcUserService.update(pcUser); } @RequestMapping(value = "/delete/{id}", method = RequestMethod.POST, consumes = "application/json", produces = "application/json") @ResponseBody public boolean delete(@PathVariable String id) { logger.debug("Delegating to service to delete existing PcUser"); return pcUserService.delete(id); } }
经过研究,我遇到了一个名为spring-test-mvc的Spring框架。看起来非常有前途,我已经设法在这方面取得了良好的开端。但是现在我有一个新问题。当我向“ / pcusers / {id}”提交GET请求时,控件将传递给负责处理该映射的read方法。在该方法内部,我有一个pcUserService进行读取。现在,问题是当我运行此测试时,真实控制器内的pcUserService实例为NULL;因此,由于无法在NULL对象上调用read而导致崩溃。
这是PcUserControllerTest代码:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:/applicationContextTest.xml") public class PcUserControllerTest { @Autowired PcUserService pcUserService; @Autowired PcUserController pcUserController; PcUser pcUser; @Before public void setUp() throws Exception { pcUser = new PcUser("John", "Li", "Weasley", "john", "john", new DateTime()); pcUserService.create(pcUser); } public void tearDown() throws Exception { pcUserService.delete(pcUser.getId()); } @Test public void shouldGetPcUser() throws Exception { standaloneSetup(pcUserController) .build() .perform(get("/pcusers/" + pcUser.getId()).accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()); } }
这是一个建议,应该给你一些想法。我假设你熟悉SpringJUnit4ClassRunner和@ContextConfiguration。首先创建一个包含PcUserController和的测试应用程序上下文PcUserService。在PcUserControllerTest下面的示例类中,Jackson用于转换JSON消息,Mockito用于模拟。
SpringJUnit4ClassRunner
@ContextConfiguration
PcUserController
PcUserService
PcUserControllerTest
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(/* Insert test application context here */) public class PcUserControllerTest { MockHttpServletRequest requestMock; MockHttpServletResponse responseMock; AnnotationMethodHandlerAdapter handlerAdapter; ObjectMapper mapper; PcUser pcUser; @Autowired PcUserController pcUserController; @Autowired PcUserService pcUserServiceMock; @Before public void setUp() { requestMock = new MockHttpServletRequest(); requestMock.setContentType(MediaType.APPLICATION_JSON_VALUE); requestMock.addHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE); responseMock = new MockHttpServletResponse(); handlerAdapter = new AnnotationMethodHandlerAdapter(); HttpMessageConverter[] messageConverters = {new MappingJacksonHttpMessageConverter()}; handlerAdapter.setMessageConverters(messageConverters); mapper = new ObjectMapper(); pcUser = new PcUser(...); reset(pcUserServiceMock); } }
现在,我们拥有创建测试所需的所有代码:
@Test public void shouldGetUser() throws Exception { requestMock.setMethod("GET"); requestMock.setRequestURI("/pcusers/1"); when(pcUserServiceMock.read(1)).thenReturn(pcUser); handlerAdapter.handle(requestMock, responseMock, pcUserController); assertThat(responseMock.getStatus(), is(HttpStatus.SC_OK)); PcUser actualPcUser = mapper.readValue(responseMock.getContentAsString(), PcUser.class); assertThat(actualPcUser, is(pcUser)); } @Test public void shouldCreateUser() throws Exception { requestMock.setMethod("POST"); requestMock.setRequestURI("/pcusers/create/1"); String jsonPcUser = mapper.writeValueAsString(pcUser); requestMock.setContent(jsonPcUser.getBytes()); handlerAdapter.handle(requestMock, responseMock, pcUserController); verify(pcUserServiceMock).create(pcUser); }