首页 > 解决方案 > 使用辅助方法为 Java 对象生成测试数据时提供默认值

问题描述

假设以下 POJO:

@Getter
@Setter
public class UserRequest {
    private String username;
    private String password;
    private String email;
}

现在我想为这个类生成各种测试数据。每当没有明确设置某些字段时,应设置默认值。请记住,我不能将 Lombok's@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, DEFAULT_PASSWORD, email);
    }

    public static UserRequest createUserRequestWithUsernameAndPassword(String username, String password) {
        return createUserRequest(username, password, 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;
    }
}

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

我的第一个想法是@Builder在方法级别上使用 Lombok 的createUserRequest()

@Builder
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;
}

这将允许以下内容:

UserRequestTestDataBuilder.builder()
  .username("foo")
  .password("bar")
  .build();

但是,这不会为(在这种情况下email)设置任何默认值。是否有一些模式可以简化这种方法?

标签: javalombokbuilder

解决方案


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

public class UserRequestTestDataUtils {
    // leave this method as such, without any null checks.
    @Builder
    public static UserRequest newUserRequest(String username, String password, 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();

推荐阅读