public Model buildWith(ModelBuilder modelBuilder) { Model model = modelBuilder.useCase("Get greeted") .basicFlow() .step("S1").system(this::promptsUserToEnterFirstName) .step("S2").user(ENTERS_FIRST_NAME).system(this::savesFirstName) .step("S3").system(this::promptsUserToEnterAge) .step("S4").user(ENTERS_AGE).system(this::savesAge) .step("S5").system(this::greetsUserWithFirstNameAndAge) .step("S6").system(this::stops) .flow("Handle out-of-bounds age").insteadOf("S5").condition(this::ageIsOutOfBounds) .step("S5a_1").system(this::informsUserAboutOutOfBoundsAge) .step("S5a_2").continuesAt("S3") .flow("Handle non-numerical age").insteadOf("S5") .step("S5b_1").on(NON_NUMERICAL_AGE).system(this::informsUserAboutNonNumericalAge) .step("S5b_2").continuesAt("S3") .build(); return model; }
public Model buildWith(ModelBuilder modelBuilder) { normalUser = modelBuilder.actor("Normal User"); anonymousUser = modelBuilder.actor("Anonymous User"); Model model = modelBuilder.useCase("Get greeted") .basicFlow() .step("S1").as(normalUser).system(this::promptsUserToEnterFirstName) .step("S2").as(normalUser).user(ENTERS_FIRST_NAME).system(this::savesFirstName) .step("S3").as(normalUser, anonymousUser).system(this::promptsUserToEnterAge) .step("S4").as(normalUser, anonymousUser).user(ENTERS_AGE).system(this::savesAge) .step("S5").as(normalUser).system(this::greetsUserWithFirstName) .step("S6").as(normalUser, anonymousUser).system(this::greetsUserWithAge) .step("S7").as(normalUser, anonymousUser).system(this::stops) .flow("Handle out-of-bounds age").insteadOf("S5").condition(this::ageIsOutOfBounds) .step("S5a_1").system(this::informsUserAboutOutOfBoundsAge) .step("S5a_2").continuesAt("S3") .flow("Handle non-numerical age").insteadOf("S5") .step("S5b_1").on(NON_NUMERICAL_AGE).system(this::informsUserAboutNonNumericalAge) .step("S5b_2").continuesAt("S3") .flow("Anonymous greeted with age only").insteadOf("S5").condition(this::ageIsOk) .step("S5c_1").as(anonymousUser).continuesAt("S6") .flow("Anonymous does not enter name").insteadOf("S1") .step("S1a_1").as(anonymousUser).continuesAt("S3") .build(); return model; }
public Model buildWith(ModelBuilder modelBuilder) { Model model = modelBuilder.useCase("Get greeted") .basicFlow() .step("S1").system(this::promptsUserToEnterFirstName) .step("S2").user(ENTERS_FIRST_NAME).system(this::savesFirstName) .step("S3").system(this::promptsUserToEnterAge) .step("S4").user(ENTERS_AGE).system(this::savesAge) .step("S5").system(this::greetsUserWithFirstNameAndAge) .build(); return model; }
@Test public void throwsExceptionWhenIncludedUseCaseIsDeclaredLater() { thrown.expect(NoSuchElementInModel.class); thrown.expectMessage(INCLUDED_USE_CASE); modelBuilder .useCase(USE_CASE) .basicFlow() .step(SYSTEM_INCLUDES_USE_CASE).includesUseCase(INCLUDED_USE_CASE) .step(SYSTEM_DISPLAYS_TEXT).system(displaysConstantText()) .useCase(INCLUDED_USE_CASE) .basicFlow() .step(SYSTEM_DISPLAYS_NUMBER).user(EntersNumber.class).system(displaysEnteredNumber()) .build(); } }
.useCase("Included use case") .basicFlow() .step("Included step").system(promptsUserToEnterName()) .useCase("Get greeted") .basicFlow() .step("S1").system(promptsUserToEnterName()) .step("S2").user(entersName()).system(greetsUser()) .step("S3").as(firstActor).user(entersName()).system(greetsUser()).reactWhile(someConditionIsFulfilled()) .step("S4").as(firstActor, secondActor).user(decidesToQuit()) .step("S5").as(firstActor, secondActor).system(promptsUserToEnterName()) .step("S6").system(quits()) .flow("Alternative flow A").insteadOf("S4") .step("S4a_1").system(blowsUp()) .step("S4a_2").continuesAt("S1") .flow("Alternative flow B").after("S3") .step("S4b_1").continuesAfter("S2") .flow("Alternative flow C").condition(thereIsNoAlternative()) .step("S5a").continuesWithoutAlternativeAt("S4") .flow("Alternative flow D").insteadOf("S4").condition(thereIsNoAlternative()) .step("S4c_1").includesUseCase("Included use case") .step("S4c_2").continuesAt("S1") .flow("EX").anytime() .step("EX1").on(Exception.class).system(logsException()) .build();
public Model buildWith(ModelBuilder modelBuilder) { Model model = modelBuilder.useCase("Feel Stuff") .basicFlow() .step("1").user(asksForPoem).system(feelStuffUseCaseRealization::writesSadPoem) .step("2").user(asksForPoem).system(feelStuffUseCaseRealization::writesHappyPoem) .step("3").user(asksForPoem).system(feelStuffUseCaseRealization::writesFunnyPoem) .build(); return model; } }
/** * Defines an "autonomous system reaction", meaning the system will react * without needing an event provided via {@link ModelRunner#reactTo(Object)}. * * @param systemReaction * the autonomous system reaction * @return the created system part of this step */ public StepSystemPart<ModelRunner> system(Runnable systemReaction) { Objects.requireNonNull(systemReaction); StepSystemPart<ModelRunner> systemPart = as(systemActor).system(systemReaction); return systemPart; }
@Test public void doesNotHandleExceptionIfNoExceptionOccurs() { Model model = modelBuilder.useCase(USE_CASE) .basicFlow() .step(SYSTEM_DISPLAYS_TEXT).system(displaysConstantText()) .flow(ALTERNATIVE_FLOW).after(SYSTEM_DISPLAYS_TEXT) .step(SYSTEM_HANDLES_EXCEPTION).on(ArrayIndexOutOfBoundsException.class).system(e -> {}) .build(); modelRunner.run(model); assertRecordedStepNames(SYSTEM_DISPLAYS_TEXT); }
@Test public void continuesAtThirdStepCalledFromFirstStepOfAlternativeFlowWithoutEvent() { Model model = modelBuilder .useCase(USE_CASE) .basicFlow() .step(CUSTOMER_ENTERS_TEXT).user(EntersText.class).system(displaysEnteredText()) .step(CUSTOMER_ENTERS_TEXT_AGAIN).user(EntersText.class).system(displaysEnteredText()) .step(CUSTOMER_ENTERS_NUMBER).user(EntersNumber.class).system(displaysEnteredNumber()) .flow(ALTERNATIVE_FLOW).insteadOf(CUSTOMER_ENTERS_TEXT_AGAIN) .step(CONTINUE).continuesAt(CUSTOMER_ENTERS_NUMBER) .build(); modelRunner.run(model).reactTo(entersText(), entersNumber()); assertRecordedStepNames(CUSTOMER_ENTERS_TEXT, CONTINUE, CUSTOMER_ENTERS_NUMBER); }
@Test public void continuesAfterSecondStepCalledFromFirstStepOfAlternativeFlowWithoutEvent() { Model model = modelBuilder .useCase(USE_CASE) .basicFlow() .step(CUSTOMER_ENTERS_TEXT).user(EntersText.class).system(displaysEnteredText()) .step(CUSTOMER_ENTERS_TEXT_AGAIN).user(EntersText.class).system(displaysEnteredText()) .step(CUSTOMER_ENTERS_NUMBER).user(EntersNumber.class).system(displaysEnteredNumber()) .flow(ALTERNATIVE_FLOW).insteadOf(CUSTOMER_ENTERS_TEXT_AGAIN) .step(CONTINUE).continuesAfter(CUSTOMER_ENTERS_TEXT_AGAIN) .build(); modelRunner.run(model).reactTo(entersText(), entersNumber()); assertRecordedStepNames(CUSTOMER_ENTERS_TEXT, CONTINUE, CUSTOMER_ENTERS_NUMBER); }
@Test public void continuesWithoutAlternativeAtFirstStepCalledFromFirstStepOfAlternativeFlowWithoutEvent() { Model model = modelBuilder .useCase(USE_CASE) .basicFlow() .step(CUSTOMER_ENTERS_TEXT).user(EntersText.class).system(displaysEnteredText()) .step(CUSTOMER_ENTERS_TEXT_AGAIN).user(EntersText.class).system(displaysEnteredText()) .step(CUSTOMER_ENTERS_NUMBER).user(EntersNumber.class).system(displaysEnteredNumber()) .flow(ALTERNATIVE_FLOW).insteadOf(CUSTOMER_ENTERS_TEXT) .step(CONTINUE).continuesWithoutAlternativeAt(CUSTOMER_ENTERS_TEXT) .build(); modelRunner.run(model).reactTo(entersText(), entersText()); assertRecordedStepNames(CONTINUE, CUSTOMER_ENTERS_TEXT, CUSTOMER_ENTERS_TEXT_AGAIN); }
@Test public void includedUseCaseCanBeRunOnItsOwn() { Model model = modelBuilder .useCase(INCLUDED_USE_CASE) .basicFlow() .step(CUSTOMER_ENTERS_NUMBER).user(EntersNumber.class).system(displaysEnteredNumber()) .useCase(USE_CASE) .basicFlow() .step(CUSTOMER_ENTERS_TEXT).user(EntersText.class).system(displaysEnteredText()) .step(SYSTEM_INCLUDES_USE_CASE).includesUseCase(INCLUDED_USE_CASE) .build(); modelRunner.run(model).reactTo(entersNumber()); assertRecordedStepNames(CUSTOMER_ENTERS_NUMBER); }
@Test public void printsTextAutonomouslyOnlyIfActorIsRightInSecondStep() { Model model = modelBuilder .useCase(USE_CASE) .basicFlow() .step(SYSTEM_DISPLAYS_TEXT).system(displaysConstantText()) .step(SYSTEM_DISPLAYS_TEXT_AGAIN).as(customer).system(displaysConstantText()) .build(); modelRunner.as(customer).run(model); assertRecordedStepNames(SYSTEM_DISPLAYS_TEXT, SYSTEM_DISPLAYS_TEXT_AGAIN); }
private FlowlessUserPart(Condition optionalCondition, Class<T> eventOrExceptionClass, long flowlessStepCounter) { this.flowlessStepCounter = flowlessStepCounter; StepPart stepPart = createStepPart(optionalCondition, eventOrExceptionClass, "S" + flowlessStepCounter); this.userPart = stepPart.on(eventOrExceptionClass); }
@Test public void throwsExceptionIfContinueAtNotExists() { thrown.expect(NoSuchElementInModel.class); thrown.expectMessage(CONTINUE); modelBuilder.useCase(USE_CASE).basicFlow().step("S1").continuesAt(CONTINUE); }
@Test public void throwsExceptionIfContinueWithoutAlternativeAtNotExists() { thrown.expect(NoSuchElementInModel.class); thrown.expectMessage(CONTINUE); modelBuilder.useCase(USE_CASE).basicFlow().step("S1").continuesWithoutAlternativeAt(CONTINUE); }
@Test public void throwsExceptionIfContinueAfterNotExists() { thrown.expect(NoSuchElementInModel.class); thrown.expectMessage(CONTINUE); modelBuilder.useCase(USE_CASE).basicFlow().step("S1").continuesAfter(CONTINUE); }
@Test public void includesUseCaseWithAlternativeFlowAtSecondStep_withFalseCondition() { Model model = modelBuilder .useCase(INCLUDED_USE_CASE) .basicFlow() .step(SYSTEM_HANDLES_EXCEPTION).user(Throwable.class).system(e -> e.printStackTrace()) .flow(ALTERNATIVE_FLOW).condition(() -> false) .step(CUSTOMER_ENTERS_NUMBER).user(EntersNumber.class).system(displaysEnteredNumber()) .useCase(USE_CASE) .basicFlow() .step(CUSTOMER_ENTERS_TEXT).user(EntersText.class).system(displaysEnteredText()) .step(SYSTEM_INCLUDES_USE_CASE).includesUseCase(INCLUDED_USE_CASE) .step(SYSTEM_DISPLAYS_TEXT).system(displaysConstantText()) .build(); modelRunner.run(model).reactTo(entersText(), entersNumber(), entersNumber()); assertRecordedStepNames(CUSTOMER_ENTERS_TEXT, SYSTEM_INCLUDES_USE_CASE); }
static Model model() { SaysHelloWorld saysHelloWorld = new SaysHelloWorld(); SaysHelloToUser saysHelloToUser = new SaysHelloToUser(); Model model = Model.builder().useCase("Say hello to world, then user") .basicFlow() .step("S1").user(ASKS_FOR_HELLO_WORLD).system(saysHelloWorld) .step("S2").user(ASKS_FOR_HELLO_TO_USER).system(saysHelloToUser) .build(); return model; }