我有一个成功的集成测试,但我想加入其中。
@Test
public void testAdd() throws Exception {
HttpHeaders httpHeaders = Common.createAuthenticationHeaders("stephane" + ":" + PASSWORD);
this.mockMvc.perform(
post("/admin").headers(httpHeaders)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.content("{ \"firstname\" : \"" + admin0.getFirstname() + "\", \"lastname\" : \"" + admin0.getLastname() + "\", \"email\" : \"" + admin0.getEmail() + "\", \"login\" : \"" + admin0.getLogin() + "\", \"password\" : \"" + admin0.getPassword() + "\", \"passwordSalt\" : \"" + admin0.getPasswordSalt() + "\" }")
).andDo(print())
.andExpect(status().isCreated())
.andExpect(jsonPath("$.firstname").value(admin0.getFirstname()))
.andExpect(jsonPath("$.lastname").value(admin0.getLastname()))
.andExpect(jsonPath("$.email").value(admin0.getEmail()))
.andExpect(jsonPath("$.login").value(admin0.getLogin()))
.andExpect(jsonPath("$.password").value(admin0.getPassword()))
.andExpect(jsonPath("$.passwordSalt").value(admin0.getPasswordSalt()))
.andExpect(header().string("Location", Matchers.containsString("/admin/")))
.andReturn();
}
例如,我可以在新创建的资源上发送GET请求。
然后我可以对它做一个DELETE请求,然后再一次以GET结束。
这是一个合理的集成测试场景吗?
为此,我需要检索已创建资源的id。
有什么办法吗?
谢谢!
的Stephane
答案 0 :(得分:1)
我可以通过这样做来解决它:
MvcResult result = this.mockMvc.perform(...)。andReturn();
使用andReturn()调用将值返回到结果变量中。
String location = result.getResponse()。getHeader(“Location”);
现在我可以使用以下场景进行测试:POST(已创建),GET(已找到),DELETE(ok),GET(未找到)
以下是整个测试:
HttpHeaders httpHeaders = Common.createAuthenticationHeaders("stephane" + ":" + PASSWORD);
MvcResult resultPost = this.mockMvc.perform(
post("/admin").headers(httpHeaders)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.content("{ \"firstname\" : \"" + admin0.getFirstname() + "\", \"lastname\" : \"" + admin0.getLastname() + "\", \"email\" : \"" + admin0.getEmail() + "\", \"login\" : \"" + admin0.getLogin() + "\", \"password\" : \"" + admin0.getPassword() + "\", \"passwordSalt\" : \"" + admin0.getPasswordSalt() + "\" }")
).andDo(print())
.andExpect(status().isCreated())
.andExpect(jsonPath("$.firstname").value(admin0.getFirstname()))
.andExpect(jsonPath("$.lastname").value(admin0.getLastname()))
.andExpect(jsonPath("$.email").value(admin0.getEmail()))
.andExpect(jsonPath("$.login").value(admin0.getLogin()))
.andExpect(jsonPath("$.password").value(admin0.getPassword()))
.andExpect(jsonPath("$.passwordSalt").value(admin0.getPasswordSalt()))
.andExpect(header().string("Location", Matchers.containsString("/admin/")))
.andReturn();
String location = resultPost.getResponse().getHeader("Location");
Pattern pattern = Pattern.compile("(\\d+)$");
Matcher matcher = pattern.matcher(location);
matcher.find();
Long id = Long.parseLong(matcher.group(), 10);
MvcResult resultGet = this.mockMvc.perform(
get("/admin/" + id)
.headers(httpHeaders)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON))
.andDo(print())
.andExpect(status().isFound())
.andReturn();
String responseContent = resultGet.getResponse().getContentAsString();
this.mockMvc.perform(
delete("/admin/" + id)
.headers(httpHeaders)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON))
.andDo(print())
.andExpect(status().isOk());
this.mockMvc.perform(
get("/admin/" + id)
.headers(httpHeaders)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON))
.andDo(print())
.andExpect(status().isNotFound());
答案 1 :(得分:0)
您可以考虑几个选项,具体取决于您要测试的内容。
最简单,最快捷的是模拟您的用户服务/存储库,或者返回用户详细信息的任何内容。使用Mockito,您可以使用以下代码:
// At start of test, we have an admin user in the mock database
when(userRepo.findOne(1)).thenReturn(myNewAdmin());
// some activities and assertions...
// At this point, we have deleted the admin, so return null.
when(userRepo.findOne(1)).thenReturn(null);
// more activities and assertions...
或者,如果您正在尝试对应用程序进行完全集成测试,并且您正在使用JPA,则定义嵌入式内存数据库相对简单,该数据库由HSQLDB或H2等实现。在这里,您需要在测试上下文中定义单独的数据源和实体管理器,并配置Hibernate(在测试上下文中)以生成不存在的模式实体。通过这种方式,您可以测试将实体插入数据库,以及它们的ID是否正确生成,查询它们,更新它们并删除它们。所有这些都在您的构建过程中。
我最近敲了一个演示应用程序,你可以在GitHub中找到它:
https://github.com/gratiartis/multids-demo
...虽然它演示了多个数据源的使用,但是可能有更简单的教程。
答案 2 :(得分:0)
我创建了一个deletehandler,以便在测试后立即从数据库中删除项目。
在测试中使用deleteHandler:
this.mockMvc.perform(post(...)).andDo(deleteResult(repository));
并在您的/src/test/java
结构中的某处创建以下类:
public class DeleteResultHandler implements ResultHandler {
private CrudRepository<IDatabaseObject, String> repository;
public DeleteResultHandler(CrudRepository repository) {
this.repository = repository;
}
public static DeleteResultHandler deleteResult(CrudRepository repository) {
return new DeleteResultHandler(repository);
}
@Override
public void handle(MvcResult result) throws Exception {
String location = result.getResponse().getHeader("Location");
String id = location.substring(location.lastIndexOf("/") + 1);
Optional<IDatabaseObject> o = repository.findById(id);
if (!o.isPresent())
return;
repository.delete(o.get());
// repository.deleteById(id);
}
}