使用辅助方法为 Java 对象生成测试数据时提供默认值

问题描述

假设有以下 POJO:

@input()
get disabled(): boolean {
  return this.internaldisabled;
}
set disabled(value: boolean) {
  console.log(value);
  this.internaldisabled = coerceBooleanProperty(value);
  if (this.internaldisabled) {
    this.input.disable();
  } else {
    this.input.enable();
  };
  this.stateChanges.next();
}

现在我想为这个类生成各种测试数据。每当某些字段未明确设置时,应设置认值。请记住,我无法将 Lombok 的 @Getter @Setter public class UserRequest { private String username; private String password; private String email; } @Builder 添加到原始类或以其他方式对其进行修改

所以我想出了以下帮助类:

@Builder.Default

虽然这对于只有一些字段的类来说是可以的,但如果有更多的字段和测试数据的某些变体,它就会变得乏味。

我的第一个想法是在 public class UserRequestTestDataUtils { public static final String DEFAULT_USERNAME = "foo"; public static final String DEFAULT_PASSWORD = "bar"; public static final String DEFAULT_EMAIL = "foo@bar.com"; public static UserRequest createuserRequestWithUsername(String username) { return createuserRequest(username,DEFAULT_PASSWORD,DEFAULT_EMAIL); } public static UserRequest createuserRequestWithPassword(String password) { return createuserRequest(DEFAULT_USERNAME,password,DEFAULT_EMAIL); } public static UserRequest createuserRequestWithEmail(String email) { return createuserRequest(DEFAULT_USERNAME,email); } public static UserRequest createuserRequestWithUsernameAndPassword(String username,String password) { return createuserRequest(username,DEFAULT_EMAIL); } public static UserRequest createuserRequest(String username,String password,String email) { final UserRequest userRequest = new UserRequest(); userRequest.setUsername(username); userRequest.setPassword(password); userRequest.setEmail(email); return userRequest; } } 方法级别使用 Lombok 的 @Builder

createuserRequest()

允许以下内容

@Builder
public static UserRequest createuserRequest(String username,String email) {
    final UserRequest userRequest = new UserRequest();
    userRequest.setUsername(username);
    userRequest.setPassword(password);
    userRequest.setEmail(email);    
    return userRequest;
}

但是,这不会为(在本例中为 UserRequestTestDataBuilder.builder() .username("foo") .password("bar") .build(); )设置任何认值。是否有某种模式可以简化这种方法

解决方法

为什么不只是...

@Getter
@Setter
public class UserRequest {
    private String username = "";
    private String password = "";
    private String email = "(unknown email)";
}

如果有人运行 new UserRequest(),那将起作用,并且 UR 将具有默认值。 .set 可用于更改任何或所有这些字段的值。

免责声明:我是 lombok 的核心贡献者之一。

-- 编辑 --

啊哈,你不能改变原来的。如果允许将 null 计为哨兵(例如,作为需要默认值的信号):

@Builder
public static UserRequest newUserRequest(String username,String password,String email) {
    UserRequest ur = new UserRequest();
    ur.setUsername(username == null ? DEFAULT_USERNAME : username);
    // etc
    return ur;
}

如果您希望 UR 设置为某些默认值,但如果有人明确执行 buildUserRequest().username(null).build(),那么 username 应该是 null,oof。如果您无法更改 UserRequest 的来源,我不确定是否有更简单的方法。

,

您实际上可以通过在您的 util 类中的一些解决方法来实现这一点,同时使用 @Builder 注释的方法添加以下与 lombok 生成的构建器类同名的类。

public class UserRequestTestDataUtils {
    // leave this method as such,without any null checks.
    @Builder
    public static UserRequest newUserRequest(String username,String email) {
        UserRequest ur = new UserRequest();
        ur.setUsername(username);
        // etc
        return ur;
    }

    // Provide the default values here.
    public static class UserRequestBuilder {
        private String username = "foo";
        private String password = "bar";
        private String email = "foo@bar.com";
    } 
}    

Lombok 仍会像往常一样在构建器类中生成其他必需的方法。您可以像这样覆盖 lombok 生成的构建器类中的任何方法/字段的行为。 (不确定这样做是否正确,但确实有效!)

注意:在构建对象时传递显式 null 会将值设置为 null

//this would generate password and email with the given default values.
UserRequestTestDataUtils.builder().username("testname").build();