CompositeObserver implements StreamObserver<T> { @Override public void onCompleted() { observers.forEach(StreamObserver::onCompleted); } CompositeObserver(Iterable<StreamObserver<? super T>> observers); @Override void onNext(T value); @Override void onError(Throwable t); @Override void onCompleted();  }
@Test @DisplayName("delegate `onCompleted` calls to wrapped observers") void delegateOnCompleted() { MemoizingObserver<String> observer1 = StreamObservers.memoizingObserver(); MemoizingObserver<String> observer2 = StreamObservers.memoizingObserver(); StreamObserver<String> observer = new CompositeObserver<>(ImmutableList.of(observer1, observer2)); observer.onCompleted(); assertThat(observer1.isCompleted()).isTrue(); assertThat(observer2.isCompleted()).isTrue(); }