有没有一种好方法可以使用模拟作为Dataflow测试的输入?

时间:2016-05-21 00:18:41

标签: google-cloud-dataflow apache-beam

我正在尝试测试DoFn<KV<String, twitter4j.Status>, String>实现,并提供测试数据作为输入。我正在探索的一个途径是使用Mockito.mock对象作为输入,因为有大量的抽象方法可以实现。但是,在我的DoFn中调用模拟方法会改变对象,这样测试框架会抱怨“值在输出后不得以任何方式变异”。

有没有其他方法可以完成我在这里尝试的方法?测试代码大致如下:

 Status status = mock(Status.class, withSettings().serializable());
 when(status.getText()).thenReturn("bar");

 Pipeline p = TestPipeline.create();
 PCollection<String> strings = p
     .apply(Create.of(KV.of("foo", status)))
     .apply(MapElements.via(new TwitterUtils.StatusToJsonFn()));

 DataflowAssert.thatSingleton(strings).isEqualTo(...);

2 个答案:

答案 0 :(得分:0)

一种方法是创建一个不可变的包装类:

class StatusWrapper implements Serializable {
    private Status status;
    private String mockText;

    // Constructor for real usage
    StatusWrapper(Status status) { this.status = status; }

    // Constructor for mocks
    StatusWrapper() {}

    StatusWrapper withMockText(String text) {
        this.mockText = text; return this;
    }

    Status toStatus() {
        if (status != null) {
            return status;
        }
        Status status = mock(Status.class);
        when(status.getText()).thenReturn(mockText);
        return status;
    }
}

Pipeline p = TestPipeline.create();
PCollection<String> strings = p
    .apply(Create.of(new StatusWrapper().withMockText("bar")))
    .apply(MapElements.via(new TwitterUtils.StatusToJsonFn()));
DataflowAssert.thatSingleton(strings).isEqualTo(...);

StatusToJsonFn需要将StatusWrapper作为参数而不是Status,并在其上调用toStatus() - 因为如果它需要Status,它将会遇到同样的问题。

在实际管道中,可以这样使用:

PCollection<Status> realStatuses = ...;
PCollection<String> strings = realStatuses
    .apply(MapElements.via(StatusWrapper::new))
    .apply(MapElements.via(new TwitterUtils.StatusToJsonFn()));

答案 1 :(得分:0)

查看DoFnTester,它允许您通过提供输入数据并对结果进行断言来测试DoFn:https://cloud.google.com/dataflow/pipelines/testing-your-pipeline