我可以比较单元测试中记录的序列化表示吗?

时间:2015-03-29 21:16:42

标签: google-cloud-dataflow

在我的DoFo的unittest中,是否可以通过比较记录的序列化表示来断言输出与预期输出匹配?

我已经定义了一个使用默认avro编码器的记录,例如

@DefaultCoder(AvroCoder.class)
public class JobLogMessage {
  @Nullable
  public String projectId;

  ...
}

我正在为一个使用DoFnTester生成JobLogMessage列表的DoFn编写单元测试,例如。

JogLogTransforms.ParsJsonDoFn doFn = new JogLogTransforms.ParsJsonDoFn();
DoFnTester<String, JobLogMessage> fnTester = DoFnTester.of(doFn);
List<JobLogMessage> outputs = fnTester.processBatch(inputs.toArray(new String[inputs.size()]));

我想验证输出是否符合预期输出。但是,如果我只使用assertEquals,我认为将使用equals方法,该方法无法正确评估相等性,除非我在JobLogMessage中显式地重载equals。

我想要做的是通过比较AvroCoder生成的序列化字节表示来比较预期和实际的JobLogMessage。 Dataflow是否为此提供了任何便利方法?

2 个答案:

答案 0 :(得分:1)

如果您对需要确定性模式的限制没有问题,可以稍微简化一下代码,以便更好地利用SDK和JDK中提供的实用程序。

public boolean equals(Object obj) {
  if (!(obj instanceof JobLogMessage)) {
    return false;
  }

  JobLogMessage other = (JobLogMessage) obj;
  AvroCoder<JobLogMessage> coder = AvroCoder.of(JobLogMessage.class);
  return Arrays.equals(CoderUtils.encodeToByteArray(this, coder),
                       CoderUtils.encodeToByteArray(obj, coder));
}

那就是说,我认为使用来自apache commons-lang的EqualsBuilderHashCodeBuilder之类的东西会更好,这些内容是为你的目标明确设计的(编码器不是旨在用作哈希和平等测试者) - 只需使用return EqualsBuilder.reflectionEquals(this, obj)

答案 1 :(得分:0)

我使用AvroCoder实现equals生成序列化表示,然后比较序列化表示。

 @Override
  public boolean equals(Object obj) {
    if (!(obj instanceof JobLogMessage)) {
      return false;
    }

    JobLogMessage other = (JobLogMessage) obj;
    AvroCoder<JobLogMessage> coder = AvroCoder.of(JobLogMessage.class);

    Coder.Context context = new Coder.Context(true);
    ByteArrayOutputStream thisStream = new ByteArrayOutputStream();
    try {
      coder.encode(this, thisStream, context);
    } catch (IOException e) {
      throw new RuntimeException("There was a problem encoding the object.", e);
    }

    ByteArrayOutputStream otherStream = new ByteArrayOutputStream();
    try {
      coder.encode(other, otherStream, context);
    } catch (IOException e) {
      throw new RuntimeException("There was a problem encoding the object.", e);
    }

    byte[] theseBytes = thisStream.toByteArray();
    byte[] otherBytes = otherStream.toByteArray();

    if (theseBytes.length != otherBytes.length) {
      return false;
    }
    for (int i = 0; i < theseBytes.length; ++i) {
      if (theseBytes[i] != otherBytes[i]) {
        return false;
      }
    }
    return true;
  }