Dropwizard资源测试,Jackson没有填充字段,反序列化和序列化?

时间:2016-11-27 14:39:48

标签: hibernate unit-testing jersey jackson dropwizard

我有一个基本的资源测试,它使用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;
  }

1 个答案:

答案 0 :(得分:0)

我可以看到解决这个问题的方法。而不是:

Entity.entity(user, MediaType.APPLICATION_JSON_TYPE)

您可以尝试使用实际用户的json(手工制作)。但是,当然,如果您使用相同的代码进行生产(而不仅仅是测试),那么它将无法正常工作。