【问题标题】:Is there a good way to use mocks as inputs to Dataflow tests?有没有一种使用模拟作为数据流测试输入的好方法?
【发布时间】:2016-05-21 00:18:40
【问题描述】:

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

【问题讨论】:

    标签: google-cloud-dataflow apache-beam


    【解决方案1】:

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

    【讨论】:

    【解决方案2】:

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

    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()));
    

    【讨论】:

    • 谢谢。我想知道 MockSettings.stubOnly() 是否也能做到这一点,但我还没有机会尝试。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-14
    • 2019-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多