【问题标题】:Dropwizard resource test, Jackson not populating field, deserializing and serializing?Dropwizard资源测试,杰克逊不填充字段,反序列化和序列化?
【发布时间】:2016-11-27 14:39:47
【问题描述】:

我有一个基本资源测试,它使用 ResourceTestRule 运行我的资源,并使用 Jersey 作为客户端来发出请求 - 其中大部分是直接从文档中获取的。问题是我想 1) 在 create 上验证 User 对象,以及 2) 在从 Object -> JSON 开始时不序列化 salt 和密码,作为一个包罗万象,因此这些永远不会在响应中公开。

测试失败并返回没有内容的 422。 Hibernate 验证错误消息永远不会通过,所以我最终看到的唯一一件事是 Response.Status.OK 断言的失败。我对password 有一个验证约束,即@NotEmpty - 将其注释掉会使测试通过。我也是@JsonIgnoreing 密码获取器,因为它很方便并且使它永远不会暴露在 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;
  }

【问题讨论】:

    标签: hibernate unit-testing jersey jackson dropwizard


    【解决方案1】:

    我可以找到解决方法。而不是:

    Entity.entity(user, MediaType.APPLICATION_JSON_TYPE)
    

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

    【讨论】:

    • 是的,我考虑过。如果没有其他方法,我可能会这样做,但不能使用内置工具进行测试会很遗憾。
    猜你喜欢
    • 1970-01-01
    • 2013-07-10
    • 2020-11-30
    • 2015-04-07
    • 2012-09-10
    • 2012-12-12
    • 2017-12-09
    • 2021-12-02
    相关资源
    最近更新 更多