java - 在 Java 中测试构建器模式

标签 java unit-testing builder

我们在代码库中广泛使用构建器模式,构建的对象都具有 toBuilder() 方法。我想编写一个单元测试,以确保在 toBuilder() 方法中没有遗漏任何字段,即,对于任何可构建对象,我想大致像这样进行测试

MyClass obj = getTestObjectWithRandomData();
assertEquals(obj, obj.toBuilder().build());

现在,我可以相当轻松地编写 getTestObjectWithRandomData() 的基本版本,它使用反射将一堆值分配给任何对象的字段。然而,问题在于 build() 通常包含大量验证检查,例如,如果某个整数不在合理范围内,这些验证检查将抛出异常。编写符合所有这些类特定验证检查的 getTestObjectWithRandomData() 的通用版本是不可能的。

那么,我怎样才能做我想做的事呢?我很想将构造代码和验证代码分离到不同的方法中,这样测试就不会在验证时失败,但这意味着人们必须记住调用 validate() 或其他任何方法创建对象后。不好。

还有其他想法吗?

最佳答案

使用 Lombok 怎么样?那是你的选择吗?它会自动生成构建器代码,您再也不用担心了。 https://projectlombok.org/features/Builder

只需使用 @Builder 注释您的类

与 Lombok

import lombok.Builder;
import lombok.Singular;
import java.util.Set;

@Builder
public class BuilderExample {
  private String name;
  private int age;
  @Singular private Set<String> occupations;
}

普通 Java

import java.util.Set;

public class BuilderExample {
  private String name;
  private int age;
  private Set<String> occupations;

  BuilderExample(String name, int age, Set<String> occupations) {
    this.name = name;
    this.age = age;
    this.occupations = occupations;
  }

  public static BuilderExampleBuilder builder() {
    return new BuilderExampleBuilder();
  }

  public static class BuilderExampleBuilder {
    private String name;
    private int age;
    private java.util.ArrayList<String> occupations;

    BuilderExampleBuilder() {
    }

    public BuilderExampleBuilder name(String name) {
      this.name = name;
      return this;
    }

    public BuilderExampleBuilder age(int age) {
      this.age = age;
      return this;
    }

    public BuilderExampleBuilder occupation(String occupation) {
      if (this.occupations == null) {
        this.occupations = new java.util.ArrayList<String>();
      }

      this.occupations.add(occupation);
      return this;
    }

    public BuilderExampleBuilder occupations(Collection<? extends String> occupations) {
      if (this.occupations == null) {
        this.occupations = new java.util.ArrayList<String>();
      }

      this.occupations.addAll(occupations);
      return this;
    }

    public BuilderExampleBuilder clearOccupations() {
      if (this.occupations != null) {
        this.occupations.clear();
      }

      return this;
    }

    public BuilderExample build() {
      // complicated switch statement to produce a compact properly sized immutable set omitted.
      // go to https://projectlombok.org/features/Singular-snippet.html to see it.
      Set<String> occupations = ...;
      return new BuilderExample(name, age, occupations);
    }

    @java.lang.Override
    public String toString() {
      return "BuilderExample.BuilderExampleBuilder(name = " + this.name + ", age = " + this.age + ", occupations = " + this.occupations + ")";
    }
  }
}

关于java - 在 Java 中测试构建器模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49633654/

相关文章:

Java方法返回数组

c# - 对使用文件系统的类进行单元测试

c++ - Boost 单元测试和 Visual Studio 2005/Visual C++ 以及 BOOST_AUTO_TEST_SUITE(stringtest) 命名空间?

java - 如何将构建器模式用于具有 JPA 的实体

android - 从 AsyncTask 调用 AlertBuilder 时出现异常

xml - Ruby XML Builder 的特殊字符

java - 防止应用程序崩溃的全局方法?

java - 如何在 Websphere 应用程序服务器中设置服务器级别自定义错误文本

c# - Moq:Mock SetUp 方法在测试期间仅返回 null

java - 如何在 Android Studio 中将数据库中的列显示到 TextView 中?