FilterPipeline implements Filter { @Override public boolean postProcess(Data data) { if (usePipeline()) { return pipeline(data); } return false; } FilterPipeline();  FilterPipeline(List<Filter> pipeline); @Override boolean preProcess(Level level, Throwable error, Map<String, Object> custom,
      String description); @Override boolean postProcess(Data data);  }
@Test public void shouldCallFiltersInOrderForPostProcess() { Filter filter1 = mock(Filter.class); Filter filter2 = mock(Filter.class); Data data = mock(Data.class); when(filter1.postProcess(data)).thenReturn(false); when(filter2.postProcess(data)).thenReturn(true); FilterPipeline sut = new FilterPipeline(asList(filter1, filter2)); boolean result = sut.postProcess(data); assertThat(result, is(true)); verify(filter1).postProcess(data); verify(filter2).postProcess(data); }
@Test public void shouldStopProcessingPostProcessIfTrueFound() { Filter filter1 = mock(Filter.class); Filter filter2 = mock(Filter.class); Data data = mock(Data.class); when(filter1.postProcess(data)).thenReturn(true); when(filter2.postProcess(data)).thenReturn(false); FilterPipeline sut = new FilterPipeline(asList(filter1, filter2)); boolean result = sut.postProcess(data); assertThat(result, is(true)); verify(filter1).postProcess(data); verify(filter2, never()).postProcess(data); }