У меня есть базовый тест ресурсов, который использует ResourceTestRule
для запуска моего ресурса и Джерси в качестве клиента, чтобы сделать запрос - большая часть этого была взята непосредственно из документов. Проблема в том, что я хочу: 1) проверить объект User
на create
и 2) НЕ сериализовать соль и пароль при переходе из объекта -> JSON в качестве учетной записи, чтобы они никогда не отображались в ответах.Тест ресурса Dropwizard, Джексон не заполняет поле, десериализует и сериализует?
Тест не работает и возвращает 422 без содержимого. Сообщение об ошибке проверки Hibernate никогда не пробивает, поэтому единственное, что я вижу, это отказ от утверждения Response.Status.OK
. У меня есть ограничение валидации на password
, которое равно @NotEmpty
- комментируя это, проходит тест. Я также @JsonIgnore
с использованием пароля, поскольку он был удобным и сделал это так, чтобы он никогда не подвергался воздействию ответа JSON, но я открыт для этого другим способом. Лучше всего предположить, что где-то во внутренних подразделениях Hibernate/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("[email protected]");
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;
}
Да, я считал это. Я бы, вероятно, сделал это, если бы не было другого способа, но было бы позором не использовать встроенные инструменты для тестирования. – Justin