2017-06-20 19 views
2

でFlux.take(継続期間を)私は春の炉心3.0.6を使用していますが、私はフラックスを返すメソッドを持っています。ユニットテストStepVerifier

public Flux<Foo> createFlux(){ 
    return Flux.<List<Foo>,String>generate(/* generator omitted for clarity's sake */) 
     .take(Duration.ofSeconds(10) 
     .flatMap(Flux::fromIterable); 
} 

ジェネレータ関数はにページ番号付きのREST APIを呼び出します結果を取得し、APIがデータを返し続けている場合は、Fluxを10秒間実行します。

単体テストを作成したいのですが、Fluxが最大10秒間だけ動作することを確認するテストを作成するのに問題があります。

私はそれは常にデータを返すように、RESTサービスを嘲笑し、この書いた:

StepVerifier.withVirtualTime(() -> createFlux()) 
    .thenAwait(Duration.ofSeconds(10)) 
    .verifyComplete(); 

を、それは失敗します。

java.lang.AssertionError: expectation "expectComplete" failed (expected: onComplete(); actual: onNext([my toString() Foo bean])) 

私はいくつかの方法で生成されたアイテムを消費する必要があることを推測し、私はそうするために正しいStepVerifierメソッドを見つけることができません。私はthenConsumeWhileを持つすべての項目をスキップしようと

EDIT

StepVerifier.withVirtualTime(() -> createFlux()) 
    .thenAwait(Duration.ofSeconds(10)) 
    .thenConsumeWhile(t -> true) 
    .verifyComplete(); 

が、今のテストだけで無期限に実行され、決して終わりません。

答えて

2

ジェネレータ実際には非常に重要なのかもしれません... StepVerifierは、無限のシーケンスに限られています。問題は、ジェネレーターとthenAwaitの両方がメインスレッドで実行されるため、無限大のジェネレーターがstepverifierの進行時間を妨げ、シーケンスがタイムアウトするのを防ぎます。

takeの期間をテストしたいので、私は仮想時間が正しいとは思わない(あなたは時間の模擬テストを行っている)。私は、テイクの持続時間でパラメータ化可能なcreateFluxメソッドを作成し、はるかに短い持続時間のためにStepVerifier.create()を実行します。

あなたは本当に仮想時間のいくつかのフォームを使用したい場合、私はそれを動作させるための最小限の要件はでSchedulerをインスタンス化することによって非仮想スレッドで発電ループを分離

  1. にあることがわかりましたテストの開始時には、StepVerifierのSuppliersubscribeOn(scheduler)を使用してください。
  2. 最初に.expectNextCount(1)に電話をかけて、時間を進める前にすべてが購読され、データが流れ出すようにします。このよう

expectNextCount(100_000)からexpectNextCount(1)を変更

public Flux<Integer> createFlux() { 
    return Flux.<List<Integer>>generate(sink -> { 
     sink.next(Arrays.asList(1, 2, 3)); 
    }) 
      .take(Duration.ofSeconds(10)) 
      .flatMap(Flux::fromIterable); 
} 

@Test 
public void so44657525() throws InterruptedException { 
    Scheduler scheduler = Schedulers.newSingle("test"); 
    AtomicInteger adder = new AtomicInteger(); 

    StepVerifier.withVirtualTime(() -> createFlux() 
      .subscribeOn(scheduler) 
      .doOnNext(v -> adder.incrementAndGet()) 
    ) 
       .expectNextCount(1) 
       .thenAwait(Duration.ofSeconds(10)) 
       .thenConsumeWhile(t -> true) 
       .verifyComplete(); 

    System.out.println("Total number of values in generated lists: " + adder.get()); 
} 

、私はTotal number of values in generated lists: 102405を印刷し、実行していたし、40msのを取りました。

+0

ありがとう、それ確かに働いた。私は '.verifyComplete()'の代わりに '.expectComplete()。verify(Duration.ofSeconds(10L))'を使います。このようにして、フラックスが10秒を超えて実行されると、アサーションエラーが発生します。 verifyCompleteを使用すると、無限に実行されます。フラックスが予想される10秒間に実行される場合、両方の解決策は問題ありません。 – dipanda

0

多分、reference guideはあなたがそれを見逃してしまった場合、正しい経路に置くことができますか?

あなたが要素またはthenConsumeWhileの数を知っていれば別にあなたが順番に一つ一つの項目に対して繰り返す必要があり、最も一般的なexpectNextから、あなたが述語に基づいて要素をスキップするexpectNextCountを使用することができ、

+0

3.0.6または3.0.7で 'consumeNextWhile'が見つかりませんでした。' thenConsumeWhile'になったと思います。シーケンスにアサーションをつけたくないので、 'thenAwait'の後に' .thenConsumeWhile(t-> true) 'を置き、すべての要素をスキップして継続時間をチェックしますが、テストは無限に実行されます – dipanda