我正在尝试测试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(...);
答案 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