@Nonnull public final Next<M, F> update(M model, E event) { MI innerModel = checkNotNull(modelExtractor().apply(model)); EI innerEvent = checkNotNull(eventExtractor().apply(event)); Next<MI, FI> innerNext = checkNotNull(innerUpdate().update(innerModel, innerEvent)); M newModel = model; boolean modelUpdated = innerNext.hasModel(); if (modelUpdated) { newModel = checkNotNull(modelUpdater().apply(model, innerNext.modelUnsafe())); } return checkNotNull( innerEffectHandler().handleInnerEffects(newModel, modelUpdated, innerNext.effects())); }
@Test public void innerUpdateCannotReturnNull() throws Exception { InnerUpdate<String, String, String, String, String, String> innerUpdate = InnerUpdate.<String, String, String, String, String, String>builder() .modelExtractor(m -> m) .eventExtractor(e -> e) .innerUpdate((model, event) -> null) .modelUpdater((m, mi) -> mi) .innerEffectHandler(ignoreEffects()) .build(); try { innerUpdate.update("model", "event"); fail("did not throw null pointer exception"); } catch (NullPointerException e) { // Success. } }
@Test public void canExtractInnerEvent() throws Exception { InnerUpdate<String, String, String, String, String, String> innerUpdate = InnerUpdate.<String, String, String, String, String, String>builder() .modelExtractor(m -> m) .eventExtractor(e -> "extracted_event") .innerUpdate((model, event) -> Next.next(event)) .modelUpdater((m, mi) -> mi) .innerEffectHandler(ignoreEffects()) .build(); Next<String, String> next = innerUpdate.update("model", "event"); assertThat(next, NextMatchers.<String, String>hasModel("extracted_event")); }
@Test public void callsInnerUpdate() throws Exception { InnerUpdate<String, String, String, String, String, String> innerUpdate = InnerUpdate.<String, String, String, String, String, String>builder() .modelExtractor(m -> m) .eventExtractor(e -> e) .innerUpdate((model, event) -> Next.next("inner_update")) .modelUpdater((m, mi) -> mi) .innerEffectHandler(ignoreEffects()) .build(); Next<String, String> next = innerUpdate.update("model", "event"); assertThat(next, NextMatchers.<String, String>hasModel("inner_update")); }
@Test public void updatedModelCallsModelUpdater() throws Exception { InnerUpdate<String, String, String, String, String, String> innerUpdate = InnerUpdate.<String, String, String, String, String, String>builder() .modelExtractor(m -> m) .eventExtractor(e -> e) .innerUpdate((model, event) -> Next.next("inner_update")) .modelUpdater((m, mi) -> "model_updater") .innerEffectHandler(ignoreEffects()) .build(); Next<String, String> next = innerUpdate.update("model", "event"); assertThat(next, NextMatchers.<String, String>hasModel("model_updater")); }
@Test public void canExtractInnerModel() throws Exception { InnerUpdate<String, String, String, String, String, String> innerUpdate = InnerUpdate.<String, String, String, String, String, String>builder() .modelExtractor(m -> "extracted_model") .eventExtractor(e -> e) .innerUpdate((model, event) -> Next.next(model)) .modelUpdater((m, mi) -> mi) .innerEffectHandler(ignoreEffects()) .build(); Next<String, String> next = innerUpdate.update("model", "event"); assertThat(next, NextMatchers.<String, String>hasModel("extracted_model")); }
@Test public void noChangeDoesNotCallModelUpdater() throws Exception { InnerUpdate<String, String, String, String, String, String> innerUpdate = InnerUpdate.<String, String, String, String, String, String>builder() .modelExtractor(m -> m) .eventExtractor(e -> e) .innerUpdate((model, event) -> noChange()) .modelUpdater((m, mi) -> "model_updater") .innerEffectHandler(ignoreEffects()) .build(); Next<String, String> next = innerUpdate.update("model", "event"); assertThat(next, NextMatchers.<String, String>hasNothing()); }
@Test public void cannotExtractNullEvent() throws Exception { InnerUpdate<String, String, String, String, String, String> innerUpdate = InnerUpdate.<String, String, String, String, String, String>builder() .modelExtractor(m -> m) .eventExtractor(e -> null) .innerUpdate((model, event) -> Next.next(model)) .modelUpdater((m, mi) -> mi) .innerEffectHandler(ignoreEffects()) .build(); try { innerUpdate.update("model", "event"); fail("did not throw null pointer exception"); } catch (NullPointerException e) { // Success. } }
@Test public void cannotExtractNullModel() throws Exception { InnerUpdate<String, String, String, String, String, String> innerUpdate = InnerUpdate.<String, String, String, String, String, String>builder() .modelExtractor(m -> null) .eventExtractor(e -> e) .innerUpdate((model, event) -> Next.next(model)) .modelUpdater((m, mi) -> mi) .innerEffectHandler(ignoreEffects()) .build(); try { innerUpdate.update("model", "event"); fail("did not throw null pointer exception"); } catch (NullPointerException e) { // Success. } }
@Test public void dispatchEffectCallsInnerEffectHandler() throws Exception { InnerUpdate<String, String, String, String, String, String> innerUpdate = InnerUpdate.<String, String, String, String, String, String>builder() .modelExtractor(m -> m) .eventExtractor(e -> e) .innerUpdate((model, event) -> dispatch(effects("1", "2", "3"))) .modelUpdater((m, mi) -> mi) .innerEffectHandler((model, updated, effects) -> Next.next("effect_handler")) .build(); Next<String, String> next = innerUpdate.update("model", "event"); assertThat(next, NextMatchers.<String, String>hasModel("effect_handler")); }
@Test public void noEffectsStillCallsInnerEffectHandler() throws Exception { InnerUpdate<String, String, String, String, String, String> innerUpdate = InnerUpdate.<String, String, String, String, String, String>builder() .modelExtractor(m -> m) .eventExtractor(e -> e) .innerUpdate((model, event) -> Next.next("inner_update")) .modelUpdater((m, mi) -> mi) .innerEffectHandler((model, updated, effects) -> Next.next("effect_handler")) .build(); Next<String, String> next = innerUpdate.update("model", "event"); assertThat(next, NextMatchers.<String, String>hasModel("effect_handler")); assertThat(next, NextMatchers.<String, String>hasNoEffects()); }
@Test public void noChangeNoEffectsStillCallsInnerEffectHandler() throws Exception { InnerUpdate<String, String, String, String, String, String> innerUpdate = InnerUpdate.<String, String, String, String, String, String>builder() .modelExtractor(m -> m) .eventExtractor(e -> e) .innerUpdate((model, event) -> noChange()) .modelUpdater((m, mi) -> mi) .innerEffectHandler((model, updated, effects) -> Next.next("effect_handler")) .build(); Next<String, String> next = innerUpdate.update("model", "event"); assertThat(next, NextMatchers.<String, String>hasModel("effect_handler")); assertThat(next, NextMatchers.<String, String>hasNoEffects()); }
@Test public void updatedModelNoEffectsStillCallsInnerEffectHandler() throws Exception { InnerUpdate<String, String, String, String, String, String> innerUpdate = InnerUpdate.<String, String, String, String, String, String>builder() .modelExtractor(m -> m) .eventExtractor(e -> e) .innerUpdate((model, event) -> Next.next("inner_update")) .modelUpdater((m, mi) -> mi) .innerEffectHandler((model, updated, effects) -> Next.next("effect_handler")) .build(); Next<String, String> next = innerUpdate.update("model", "event"); assertThat(next, NextMatchers.<String, String>hasModel("effect_handler")); assertThat(next, NextMatchers.<String, String>hasNoEffects()); } }