Spring Framework TEST RESTful Web 服务(控制器)离线即无服务器,无数据库
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9138555/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring Framework TEST RESTful Web Service (Controller) Offline i.e. No Server, No Database
提问by jsf
I have a very simple RESTful Controller that consumes and produces JSON. I need to test this controller offline i.e. no server running, no database running. And I am going nuts for not being able to find a solution. My intial test cases will include:
我有一个非常简单的 RESTful 控制器,它使用和生成 JSON。我需要离线测试这个控制器,即没有服务器运行,没有数据库运行。我因为无法找到解决方案而发疯。我的初始测试用例将包括:
- Test REST URIs i.e. GET, POST, PUT, DELETE - I must be able to Assert data returned against data sent.
- Assert will test JSON data
- 测试 REST URI,即 GET、POST、PUT、DELETE - 我必须能够根据发送的数据断言返回的数据。
- 断言将测试 JSON 数据
I have the following URIs:
我有以下 URI:
- /pcusers - Returns all users
- /pcusers/{id} - Return a specific user
- /pcusers/create/{pcuser} - Add user to db
- /pcusers/update/{pcuser} - Update user
- /pcusers/delete/{id} - Delete User
- /pcusers - 返回所有用户
- /pcusers/{id} - 返回特定用户
- /pcusers/create/{pcuser} - 将用户添加到数据库
- /pcusers/update/{pcuser} - 更新用户
- /pcusers/delete/{id} - 删除用户
NOTE: This is NOT a typical MVC application. I DO NOT have Views. I have a pure REST controller that spits out JSON and consumes data in JSON format.
注意:这不是典型的 MVC 应用程序。我没有意见。我有一个纯 REST 控制器,它输出 JSON 并使用 JSON 格式的数据。
If someone could guide me in the right direction would be really appreciated.
如果有人能指导我朝着正确的方向前进,我将不胜感激。
Just to be clear how my code looks like:
只是为了清楚我的代码是什么样子的:
@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);
}
}
UPDATE (2/5/2012):After some research, I came across a Spring framework called spring-test-mvc. It looks very promising and I have managed to get a good start on this. But now I have a new problem. When I submit a GET request to "/pcusers/{id}", the control is passed to readmethod which is responsible for handling that mapping. Inside that method I have a pcUserServicethat does a read. Now, the problem is when I run this test, the pcUserServiceinstance inside real controller is NULL; and therefore it ends up crashing as read cannot be called on a NULL object.
更新(2/5/2012):经过一些研究,我遇到了一个名为spring-test-mvc的 Spring 框架。它看起来非常有前途,我已经设法在这方面取得了良好的开端。但现在我有一个新问题。当我向“/pcusers/{id}”提交 GET 请求时,控制被传递给负责处理该映射的read方法。在该方法中,我有一个pcUserService进行读取。现在,问题是当我运行此测试时,真实控制器中的pcUserService实例为 NULL;因此它最终崩溃,因为无法在 NULL 对象上调用 read 。
Here's PcUserControllerTestcode:
这是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());
}
}
采纳答案by matsev
Here is one suggestion that should give you some ideas. I assume that you are familiar with the SpringJUnit4ClassRunnerand the @ContextConfiguration. Start by creating an test application context that contains PcUserControllerand a mocked PcUserService. In the example PcUserControllerTestclass below, Hymanson is used to convert JSON messages and Mockito is used for mocking.
这是一个建议,应该会给你一些想法。我假设您熟悉SpringJUnit4ClassRunner和@ContextConfiguration。首先创建一个测试应用程序上下文,其中包含PcUserController一个模拟的PcUserService. 在PcUserControllerTest下面的示例类中,Hymanson 用于转换 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 MappingHymansonHttpMessageConverter()};
handlerAdapter.setMessageConverters(messageConverters);
mapper = new ObjectMapper();
pcUser = new PcUser(...);
reset(pcUserServiceMock);
}
}
Now, we have all the code needed to create the tests:
现在,我们拥有创建测试所需的所有代码:
@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);
}

![无法为 XML 架构命名空间找到 Spring NamespaceHandler [http://www.springframework.org/schema/batch]](/res/img/loading.gif)