FilterPipeline implements Filter { @Override public boolean preProcess(Level level, Throwable error, Map<String, Object> custom, String description) { if (usePipeline()) { return pipeline(level, error, custom, description); } 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 shouldCallFiltersInOrderForPreProcess() { Filter filter1 = mock(Filter.class); Filter filter2 = mock(Filter.class); when(filter1.preProcess(any(), any(), any(), any())).thenReturn(false); when(filter2.preProcess(any(), any(), any(), any())).thenReturn(true); Level level = Level.ERROR; Throwable error = new RuntimeException("Something went wrong."); Map<String, Object> custom = emptyMap(); String description = "Error description"; FilterPipeline sut = new FilterPipeline(asList(filter1, filter2)); boolean result = sut.preProcess(level, error, custom, description); assertThat(result, is(true)); verify(filter1).preProcess(level, error, custom, description); verify(filter2).preProcess(level, error, custom, description); }
@Test public void shouldStopProcessingPreProcessIfTrueFound() { Filter filter1 = mock(Filter.class); Filter filter2 = mock(Filter.class); when(filter1.preProcess(any(), any(), any(), any())).thenReturn(true); when(filter2.preProcess(any(), any(), any(), any())).thenReturn(false); Level level = Level.ERROR; Throwable error = new RuntimeException("Something went wrong."); Map<String, Object> custom = emptyMap(); String description = "Error description"; FilterPipeline sut = new FilterPipeline(asList(filter1, filter2)); boolean result = sut.preProcess(level, error, custom, description); assertThat(result, is(true)); verify(filter1).preProcess(level, error, custom, description); verify(filter2, never()).preProcess(level, error, custom, description); }