Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用Java测试builder模式_Java_Unit Testing_Builder - Fatal编程技术网

用Java测试builder模式

用Java测试builder模式,java,unit-testing,builder,Java,Unit Testing,Builder,我们在代码库中广泛使用构建器模式,构建的对象都有一个toBuilder()方法。我想编写一个单元测试,确保在toBuilder()方法中没有忘记任何字段,也就是说,对于任何可构建对象,我想进行大致如下的测试 MyClass obj = getTestObjectWithRandomData(); assertEquals(obj, obj.toBuilder().build()); 现在,我可以相当轻松地编写一个基本版本的getestobjectwithrandomdata(),它使用反射为任

我们在代码库中广泛使用构建器模式,构建的对象都有一个
toBuilder()
方法。我想编写一个单元测试,确保在
toBuilder()
方法中没有忘记任何字段,也就是说,对于任何可构建对象,我想进行大致如下的测试

MyClass obj = getTestObjectWithRandomData();
assertEquals(obj, obj.toBuilder().build());
现在,我可以相当轻松地编写一个基本版本的
getestobjectwithrandomdata()
,它使用反射为任何对象的字段分配一组值。然而,问题是
build()
通常包含大量的验证检查,例如,如果某个整数不在正常范围内,这些检查将引发异常。编写符合所有这些特定于类的验证检查的通用版本的
GetTestObject WithRandomData()
是不可能的

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


还有其他想法吗?

使用龙目山怎么样?这是你的选择吗?它将自动生成生成器代码,您再也不用担心它了。

只需使用
@Builder

与龙目

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;
}
导入lombok.Builder;
进口龙目山。单数;
导入java.util.Set;
@建筑商
公共类生成器示例{
私有字符串名称;
私人互联网;
@单一的私人职业;
}
香草爪哇

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 + ")";
    }
  }
}
import java.util.Set;
公共类生成器示例{
私有字符串名称;
私人互联网;
私人职业;
BuilderExample(字符串名称、整数年龄、设置职业){
this.name=名称;
这个。年龄=年龄;
这个职业=职业;
}
公共静态构建器ExampleBuilder(){
返回新的BuilderExampleBuilder();
}
公共静态类生成器ExampleBuilder{
私有字符串名称;
私人互联网;
私有java.util.ArrayList职业;
BuilderExampleBuilder(){
}
公共构建器示例构建器名称(字符串名称){
this.name=名称;
归还这个;
}
公共建筑示例建筑商年龄(整数年龄){
这个。年龄=年龄;
归还这个;
}
公共构建器示例构建器占用(字符串占用){
如果(this.occulations==null){
this.occulations=new java.util.ArrayList();
}
本.职业.添加(职业);
归还这个;
}

public builder示例builder职业(集合为什么无法在getTestWithRandomData()中随机分配可接受的值)?在编写代码时,请询问所有的if语句和抛出,以及基本上所有的分支和圈竞争性,因为您现在必须去测试它们中的每一个。过去,我在类中使用了一个静态方法:
MyClass.createTestObject()
。它在没有构建器的情况下构建了一个有效的对象,但所有字段都是有效的。随机性不是必需的,覆盖率是必需的。这对我来说是一种不必要的感觉。如果你知道构建器曾经正常工作过一次,并且你已经使用反射或其他一般方法构建了它,为什么你会停止相信它?看起来你坚持要n每次使用都要测试它,因为你想看到100%的代码覆盖率。这是一种你应该战胜的疾病。这是一个好主意。我以前见过这个库。不过,我的犹豫有两个方面。第一,我不确定我的同事和我是否准备好全力以赴。第二,使用Lombok意味着我必须放弃ctor中的那些验证检查。如果没有这些,就没有问题了。我已经晚了很多年,但是你也可以覆盖Lombok为你生成的内容。我偶尔这样做是为了提供一些验证检查。OTOH,你越是覆盖Lombok,代码就变得越惊人,所以它是一个混合包。