Spring Framework测试RESTful Web服务(控制器)离线,即没有服务器,没有数据库



我有一个非常简单的RESTful控制器,它使用并生成JSON。我需要离线测试这个控制器,即没有服务器运行,没有数据库运行。我为找不到解决方案而发疯。我的初始测试用例将包括:

  • 测试RESTURI,即GET、POST、PUT、DELETE——我必须能够根据发送的数据断言返回的数据
  • Assert将测试JSON数据

我有以下URI:

  • /pcusers-返回所有用户
  • /pcusers/{id}-返回特定用户
  • /pcusers/create/{pcuser}-将用户添加到数据库
  • /pcusers/update/{pcuser}-更新用户
  • /pcusers/delete/{id}-删除用户

注意:这不是一个典型的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);
    }
}

更新(2/5/2012):经过一些研究,我发现了一个名为Spring-test-mvc的Spring框架。这看起来很有希望,我已经取得了一个良好的开端。但现在我有了一个新问题。当我向"/pusers/{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用于嘲讽。

@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);
}

相关内容

  • 没有找到相关文章

最新更新