我有一个基本的资源测试,它使用ResourceTestRule
来运行我的资源,并使用Jersey作为客户端来发出请求 - 其中大部分是直接从文档中获取的。问题是我想1)在User
上验证create
对象,以及2)在从对象转发时不要序列化盐和密码 - > JSON,作为一个catchall,所以这些从未在响应中公开。
测试失败并返回422没有内容。 Hibernate验证错误消息永远不会通过,所以我最终看到的是Response.Status.OK
断言的失败。我在password
上有@NotEmpty
的验证限制 - 对此进行评论会使测试通过。我也是@JsonIgnore
密码获取器,因为它很方便并且使它永远不会暴露在JSON响应中,但我愿意以不同的方式做这件事。我最好的猜测是,在Hibernate / Jersey内部的某个地方,我传递给Jersey请求的实体(Entity.entity(user, MediaType.APPLICATION_JSON_TYPE)
)正在反序列化并再次序列化,密码因为无法获取而丢失。
以下是测试规则:
@ClassRule public static final ResourceTestRule
userResource =
ResourceTestRule.builder().addResource(new UserResource(USER_DAO, PERSON_DAO)).build();
在assertThat(response.getStatusInfo()).isEqualTo(Response.Status.OK);
失败的测试体:
when(USER_DAO.save(any(User.class))).thenReturn(Optional.of(user));
when(PERSON_DAO.save(any(Person.class))).thenReturn(Optional.of(person));
final Response
response =
userResource.client().target("/user").request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.entity(user, MediaType.APPLICATION_JSON_TYPE));
assertThat(response.getStatusInfo()).isEqualTo(Response.Status.OK);
verify(USER_DAO).save(userCaptor.capture());
verify(PERSON_DAO).save(personCaptor.capture());
User savedUser = userCaptor.getValue();
assertThat(savedUser).isEqualToIgnoringGivenFields(user, "salt", "password", "person");
assertThat(savedUser.getPerson()).isEqualToComparingFieldByFieldRecursively(user.getPerson());
这是实际的资源方法:
@POST
@Timed
public User create(@NotNull @Valid User user) {
if (user.getPerson() != null) {
try {
personDAO.save(user.getPerson());
// todo justin - abstract this
} catch (DuplicateKeyException e) {
throw new WebApplicationException("That person exists already.", Response.SC_BAD_REQUEST);
}
}
try {
user = userDAO.save(user).get();
} catch (DuplicateKeyException e) {
throw new WebApplicationException("That user exists already.", Response.SC_BAD_REQUEST);
}
return user;
}
这是预期的用户(我从模拟UserDAO
返回的用户):
user = new User();
user.setEmail("justin@email.com");
user.setPassword("test");
person = new Person();
person.setFirstName("Justin");
person.setLastName("K");
user.setPerson(person);
User
类的相关部分:
public class User extends BaseModel implements Principal {
@Id
@JsonSerialize(using = ToStringSerializer.class)
private ObjectId id = new ObjectId();
@Email
@NotBlank
private String email;
@NotEmpty
private byte[] password;
private byte[] salt = Security.getSalt();
public ObjectId getId() {
return id;
}
public void setId(ObjectId id) {
this.id = id;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@JsonIgnore // ignored when serialized FROM object TO json
public byte[] getPassword() {
return password;
}
@JsonProperty
public void setPassword(byte[] password) {
this.password = password;
}
@JsonProperty
public void setPassword(String password) {
this.password = Security.hashPassword(password.toCharArray(), this.getSalt());
}
@JsonIgnore // ignored when serialized FROM object TO json
public byte[] getSalt() {
return salt;
}
@JsonProperty
public void setSalt(byte[] salt) {
this.salt = salt;
}
答案 0 :(得分:0)
我可以看到解决这个问题的方法。而不是:
Entity.entity(user, MediaType.APPLICATION_JSON_TYPE)
您可以尝试使用实际用户的json(手工制作)。但是,当然,如果您使用相同的代码进行生产(而不仅仅是测试),那么它将无法正常工作。