2016-05-21 3 views
0

Ich versuche eine DoFn<KV<String, twitter4j.Status>, String> Implementierung zu testen und Testdaten als Eingabe bereitzustellen. Eine Möglichkeit, die ich untersuchte, war die Verwendung eines Objekts Mockito.mock als Eingabe, da ansonsten eine große Anzahl abstrakter Methoden implementiert werden müssen. Der Aufruf der verspotteten Methoden in meinem DoFn ändert jedoch das Objekt, so dass das Testframework beschwert, dass "Werte nicht in irgendeiner Weise mutiert werden müssen, nachdem es ausgegeben wurde".Gibt es eine gute Möglichkeit, Mocks als Eingaben für Dataflow-Tests zu verwenden?

Gibt es einen alternativen Weg, um das zu erreichen, was ich hier versuche? Der Testcode ist in etwa:

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

Antwort

0

Ein Ansatz ist eine unveränderliche Wrapper-Klasse zu erstellen:

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 wird StatusWrapper als Argument statt Status, nehmen müssen und toStatus() auf ihn nennen - weil Wenn es Status dauert, leidet es unter dem gleichen Problem.

In einer realen Pipeline dies wie folgt verwendet werden kann:

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

Dank. Ich frage mich, ob MockSettings.stubOnly() dies auch erreichen würde, aber ich hatte keine Chance, es auszuprobieren. –

Verwandte Themen