Java 如何对基于KinesRecord的DoFn进行单元测试?

Java 如何对基于KinesRecord的DoFn进行单元测试?,java,apache-beam,amazon-kinesis-analytics,Java,Apache Beam,Amazon Kinesis Analytics,我正在开始一个从AWS Kinesis读取的Beam项目,所以我有一个简单的DoFn,它接受KinesRecord并记录内容。我想编写一个单元测试来运行这个DoFn并证明它是有效的。不过,使用KinesRecord进行单元测试已被证明具有挑战性 当我尝试仅使用Create.of(testKinesisRecord)时,会出现此错误: 正如错误所暗示的那样,我已经尝试使用“withCoder”显式地提供kinesRecordCoder,但它是一个私有类。也许有另一种方法可以对DoFn进行单元测试

我正在开始一个从AWS Kinesis读取的Beam项目,所以我有一个简单的DoFn,它接受KinesRecord并记录内容。我想编写一个单元测试来运行这个DoFn并证明它是有效的。不过,使用KinesRecord进行单元测试已被证明具有挑战性

当我尝试仅使用
Create.of(testKinesisRecord)
时,会出现此错误:

正如错误所暗示的那样,我已经尝试使用“withCoder”显式地提供kinesRecordCoder,但它是一个私有类。也许有另一种方法可以对DoFn进行单元测试

测试代码:

public class MyProjectTests {
    @Rule
    public TestPipeline p = TestPipeline.create();

    @Test
    public void testPoC() {
        var testKinesisRecord = new KinesisRecord(
                ByteBuffer.wrap("SomeData".getBytes()),
                "seq01",
                12,
                "pKey",
                Instant.now().minus(Duration.standardHours(4)),
                Instant.now(),
                "MyStream",
                "shard-001"
        );


        PCollection<Void> output =
                p.apply(Create.of(testKinesisRecord))
                        .apply(ParDo.of(new MyProject.PrintRecordFn()));

        var result = p.run();
        result.waitUntilFinish();
        result.metrics().allMetrics().getCounters().forEach(longMetricResult -> {
            Assertions.assertEquals(1, longMetricResult.getCommitted().intValue());
        });
    }
}
公共类MyProjectTests{
@统治
public TestPipeline p=TestPipeline.create();
@试验
公共void testPoC(){
var testkinesrecord=新的kinesrecord(
ByteBuffer.wrap(“SomeData.getBytes()),
“seq01”,
12,
“pKey”,
Instant.now()减(Duration.standardHours(4)),
立即。现在(),
“MyStream”,
“碎片-001”
);
采集输出=
p、 应用(创建(TestKinesRecord))
.apply(ParDo.of(new MyProject.PrintRecordFn());
var result=p.run();
result.waitUntilFinish();
result.metrics().allMetrics().getCounters().forEach(longMetricResult->{
assertEquals(1,longMetricResult.getCommitted().intValue());
});
}
}
DoFn代码:

  static class PrintRecordFn extends DoFn<KinesisRecord, Void> {
    private static final Logger LOG = LoggerFactory.getLogger(PrintRecordFn.class);
    private final Counter items = Metrics.counter(PrintRecordFn.class, "itemsProcessed");

    @ProcessElement
    public void processElement(@Element KinesisRecord element) {
      items.inc();

      LOG.info("Stream: `{}` Shard: `{}` Arrived at `{}`\nData: {}",
              element.getStreamName(),
              element.getShardId(),
              element.getApproximateArrivalTimestamp(),
              element.getDataAsBytes());
    }
  }
静态类PrintRecordFn扩展了DoFn{
私有静态最终记录器LOG=LoggerFactory.getLogger(PrintRecordFn.class);
私有最终计数器项=Metrics.Counter(PrintRecordFn.class,“itemsProcessed”);
@过程元素
public void processElement(@Element kinesRecord Element){
items.inc();
LOG.info(“流:`{}`Shard:`{}`到达`{}`\n数据:{}”,
元素。getStreamName(),
元素。getShardId(),
元素。getApproximateArrivalTimestamp(),
元素。getDataAsBytes());
}
}

kinesRecordCoder
应该用于内部目的,因此它是包私有的。同时,您可以提供自定义
AWSClientsProvider
,并使用它生成测试数据。作为一个例子,请看一看和定制

  static class PrintRecordFn extends DoFn<KinesisRecord, Void> {
    private static final Logger LOG = LoggerFactory.getLogger(PrintRecordFn.class);
    private final Counter items = Metrics.counter(PrintRecordFn.class, "itemsProcessed");

    @ProcessElement
    public void processElement(@Element KinesisRecord element) {
      items.inc();

      LOG.info("Stream: `{}` Shard: `{}` Arrived at `{}`\nData: {}",
              element.getStreamName(),
              element.getShardId(),
              element.getApproximateArrivalTimestamp(),
              element.getDataAsBytes());
    }
  }