/** * 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; }
/** * Defines an "autonomous system reaction", meaning the system will react * without needing an event provided via {@link ModelRunner#reactTo(Object)}. * Instead, the model runner provides itself as an event to the system reaction. * * @param modelRunnerConsumer * the autonomous system reaction (that needs information from a model runner to work) * @return the created system part of this step */ public StepSystemPart<ModelRunner> system(Consumer<ModelRunner> modelRunnerConsumer) { Objects.requireNonNull(modelRunnerConsumer); StepSystemPart<ModelRunner> systemPart = as(systemActor).system(modelRunnerConsumer); return systemPart; }
@Test public void createsSingleActorWithSingleUseCase() { UseCasePart useCasePart = modelBuilder.useCase(USE_CASE); Model model = useCasePart.basicFlow() .step(CUSTOMER_ENTERS_TEXT).as(customer).user(EntersText.class).system(displaysEnteredText()) .build(); Actor customerActor = model.findActor(CUSTOMER); Set<UseCase> useCases = customerActor.getUseCases(); assertEquals(1, useCases.size()); UseCase actualUseCase = useCases.iterator().next(); assertEquals(USE_CASE, actualUseCase.getName()); }
@Test public void printsTextAutonomouslyOnlyIfActorIsRightInFirstStep() { Model model = modelBuilder .useCase(USE_CASE) .basicFlow() .step(SYSTEM_DISPLAYS_TEXT).as(customer).system(displaysConstantText()) .step(SYSTEM_DISPLAYS_TEXT_AGAIN).as(secondActor).system(displaysConstantText()) .build(); modelRunner.as(customer).run(model); assertRecordedStepNames(SYSTEM_DISPLAYS_TEXT); }
@Test public void continuesAtCalledFromFirstStepOfAlternativeFlowWithRightActor() { Model model = modelBuilder .useCase(USE_CASE) .basicFlow() .step(CUSTOMER_ENTERS_TEXT).as(secondActor).user(EntersText.class).system(displaysEnteredText()) .step(CUSTOMER_ENTERS_TEXT_AGAIN).as(secondActor, customer).user(EntersText.class).system(displaysEnteredText()) .step(CUSTOMER_ENTERS_NUMBER).as(secondActor, customer).user(EntersNumber.class).system(displaysEnteredNumber()) .flow(ALTERNATIVE_FLOW).insteadOf(CUSTOMER_ENTERS_TEXT) .step(CONTINUE).as(customer).continuesAt(CUSTOMER_ENTERS_TEXT_AGAIN) .build(); modelRunner.as(customer).run(model).reactTo(entersText(), entersNumber()); assertRecordedStepNames(CONTINUE, CUSTOMER_ENTERS_TEXT_AGAIN, CUSTOMER_ENTERS_NUMBER); }
@Test public void continuesAfterCalledFromFirstStepOfAlternativeFlowWithRightActor() { Model model = modelBuilder .useCase(USE_CASE) .basicFlow() .step(CUSTOMER_ENTERS_TEXT).as(secondActor).user(EntersText.class).system(displaysEnteredText()) .step(CUSTOMER_ENTERS_TEXT_AGAIN).as(secondActor, customer).user(EntersText.class).system(displaysEnteredText()) .step(CUSTOMER_ENTERS_NUMBER).as(secondActor, customer).user(EntersNumber.class).system(displaysEnteredNumber()) .flow(ALTERNATIVE_FLOW).insteadOf(CUSTOMER_ENTERS_TEXT) .step(CONTINUE).as(customer).continuesAfter(CUSTOMER_ENTERS_TEXT) .build(); modelRunner.as(customer).run(model).reactTo(entersText(), entersNumber()); assertRecordedStepNames(CONTINUE, CUSTOMER_ENTERS_TEXT_AGAIN, CUSTOMER_ENTERS_NUMBER); }
@Test public void continuesWithoutAlternativeAtNotCalledWhenActorIsWrong() { Model model = modelBuilder .useCase(USE_CASE) .basicFlow() .step(CUSTOMER_ENTERS_TEXT).as(secondActor).user(EntersText.class).system(displaysEnteredText()) .step(CUSTOMER_ENTERS_TEXT_AGAIN).as(secondActor, customer).user(EntersText.class).system(displaysEnteredText()) .step(CUSTOMER_ENTERS_NUMBER).as(secondActor, customer).user(EntersNumber.class).system(displaysEnteredNumber()) .flow(ALTERNATIVE_FLOW).insteadOf(CUSTOMER_ENTERS_TEXT) .step(CONTINUE).as(customer).continuesWithoutAlternativeAt(CUSTOMER_ENTERS_TEXT) .build(); modelRunner.as(secondActor).run(model).reactTo(entersText(), entersText(), entersNumber()); assertRecordedStepNames(CUSTOMER_ENTERS_TEXT, CUSTOMER_ENTERS_TEXT_AGAIN, CUSTOMER_ENTERS_NUMBER); }
@Test public void continuesAtNotCalledWhenActorIsWrong() { Model model = modelBuilder .useCase(USE_CASE) .basicFlow() .step(CUSTOMER_ENTERS_TEXT).as(secondActor).user(EntersText.class).system(displaysEnteredText()) .step(CUSTOMER_ENTERS_TEXT_AGAIN).as(secondActor, customer).user(EntersText.class).system(displaysEnteredText()) .step(CUSTOMER_ENTERS_NUMBER).as(secondActor, customer).user(EntersNumber.class).system(displaysEnteredNumber()) .flow(ALTERNATIVE_FLOW).insteadOf(CUSTOMER_ENTERS_TEXT) .step(CONTINUE).as(customer).continuesAt(CUSTOMER_ENTERS_TEXT_AGAIN) .build(); modelRunner.as(secondActor).run(model).reactTo(entersText(), entersText(), entersNumber()); assertRecordedStepNames(CUSTOMER_ENTERS_TEXT, CUSTOMER_ENTERS_TEXT_AGAIN, CUSTOMER_ENTERS_NUMBER); }
@Test public void continuesAfterNotCalledWhenActorIsWrong() { Model model = modelBuilder .useCase(USE_CASE) .basicFlow() .step(CUSTOMER_ENTERS_TEXT).as(secondActor).user(EntersText.class).system(displaysEnteredText()) .step(CUSTOMER_ENTERS_TEXT_AGAIN).as(secondActor, customer).user(EntersText.class).system(displaysEnteredText()) .step(CUSTOMER_ENTERS_NUMBER).as(secondActor, customer).user(EntersNumber.class).system(displaysEnteredNumber()) .flow(ALTERNATIVE_FLOW).insteadOf(CUSTOMER_ENTERS_TEXT) .step(CONTINUE).as(customer).continuesAfter(CUSTOMER_ENTERS_TEXT) .build(); modelRunner.as(secondActor).run(model).reactTo(entersText(), entersText(), entersNumber()); assertRecordedStepNames(CUSTOMER_ENTERS_TEXT, CUSTOMER_ENTERS_TEXT_AGAIN, CUSTOMER_ENTERS_NUMBER); }
@Test public void continuesWithoutAlternativeAtCalledFromFirstStepOfAlternativeFlowWithRightActor() { Model model = modelBuilder .useCase(USE_CASE) .basicFlow() .step(CUSTOMER_ENTERS_TEXT).as(customer).user(EntersText.class).system(displaysEnteredText()) .step(CUSTOMER_ENTERS_TEXT_AGAIN).as(secondActor, customer).user(EntersText.class).system(displaysEnteredText()) .step(CUSTOMER_ENTERS_NUMBER).as(secondActor, customer).user(EntersNumber.class).system(displaysEnteredNumber()) .flow(ALTERNATIVE_FLOW).insteadOf(CUSTOMER_ENTERS_TEXT) .step(CONTINUE).as(customer).continuesWithoutAlternativeAt(CUSTOMER_ENTERS_TEXT) .build(); modelRunner.as(customer).run(model).reactTo(entersText(), entersText(), entersNumber()); assertRecordedStepNames(CONTINUE, CUSTOMER_ENTERS_TEXT, CUSTOMER_ENTERS_TEXT_AGAIN, CUSTOMER_ENTERS_NUMBER); }
@Test public void doesNotReactIfStepHasRightActorButFalseCondition() { Model model = modelBuilder .useCase(USE_CASE) .basicFlow() .step(CUSTOMER_ENTERS_TEXT) .as(secondActor).user(EntersText.class).system(displaysEnteredText()) .flow(ALTERNATIVE_FLOW).condition(() -> false) .step(THIS_STEP_SHOULD_BE_SKIPPED) .as(customer).user(EntersText.class).system(displaysEnteredText()) .build(); modelRunner.as(customer).run(model); Optional<Step> lastStepRun = modelRunner.reactTo(entersText()); assertFalse(lastStepRun.isPresent()); }
@Test public void twoSequentialStepsReactWhenSeveralActorsContainRightActorAtFirstPosition() { Model model = modelBuilder .useCase(USE_CASE) .basicFlow() .step(CUSTOMER_ENTERS_TEXT) .as(customer).user(EntersText.class).system(displaysEnteredText()) .step(CUSTOMER_ENTERS_TEXT_AGAIN) .as(customer, secondActor).user(EntersText.class).system(displaysEnteredText()) .build(); modelRunner.as(customer).run(model); reactToAndAssertEvents(entersText(), entersText()); }
@Test public void twoSequentialStepsReactWhenSeveralActorsContainRightActorAtSecondPosition() { Model model = modelBuilder .useCase(USE_CASE) .basicFlow() .step(CUSTOMER_ENTERS_TEXT) .as(customer).user(EntersText.class).system(displaysEnteredText()) .step(CUSTOMER_ENTERS_TEXT_AGAIN) .as(secondActor, customer).user(EntersText.class).system(displaysEnteredText()) .build(); modelRunner.as(customer).run(model); reactToAndAssertEvents(entersText(), entersText()); }
@Test public void onlyStepWithRightActorReacts() { Model model = modelBuilder .useCase(USE_CASE) .basicFlow() .step(CUSTOMER_ENTERS_TEXT) .as(customer).user(EntersText.class).system(displaysEnteredText()) .step(CUSTOMER_ENTERS_TEXT_AGAIN) .as(secondActor).user(EntersText.class).system(throwsRuntimeException()) .build(); modelRunner.as(customer).run(model).reactTo(entersText(), entersText()); assertRecordedStepNames(CUSTOMER_ENTERS_TEXT); }
@Test public void createsSingleStepThatPerformsSystemReactionAutomaticallyForSpecificActor() { UseCasePart useCasePart = modelBuilder.useCase(USE_CASE); Model model = useCasePart.basicFlow() .step(SYSTEM_DISPLAYS_TEXT).as(customer).system(displaysConstantText()) .build(); Collection<Step> steps = useCasePart.getUseCase().getSteps(); assertEquals(1, steps.size()); Step step = steps.iterator().next(); assertEquals(SYSTEM_DISPLAYS_TEXT, step.getName()); assertEquals(USE_CASE, step.getUseCase().getName()); assertTrue(model.hasActor(customer.getName())); assertEquals(customer, step.getActors()[0]); }
@Test public void twoSequentialStepsReactOnlyWhenActorIsRight() { Model model = modelBuilder .useCase(USE_CASE) .basicFlow() .step(CUSTOMER_ENTERS_TEXT) .as(customer).user(EntersText.class).system(displaysEnteredText()) .step(CUSTOMER_ENTERS_TEXT_AGAIN) .as(secondActor).user(EntersText.class).system(displaysEnteredText()) .build(); modelRunner.as(customer).run(model).reactTo(entersText(), entersText()); assertRecordedStepNames(CUSTOMER_ENTERS_TEXT); }
@Test public void twoSequentialStepsReactWhenRunningWithDifferentActors() { Model model = modelBuilder .useCase(USE_CASE) .basicFlow() .step(CUSTOMER_ENTERS_TEXT) .as(customer).user(EntersText.class).system(displaysEnteredText()) .step(CUSTOMER_ENTERS_NUMBER) .as(secondActor).user(EntersNumber.class).system(displaysEnteredNumber()) .build(); modelRunner.as(customer).run(model).reactTo(entersText()); modelRunner.as(secondActor).reactTo(entersNumber()); assertRecordedStepNames(CUSTOMER_ENTERS_TEXT, CUSTOMER_ENTERS_NUMBER); }
@Test public void twoSequentialStepsReactWhenActorIsChanged() { Model model = modelBuilder .useCase(USE_CASE) .basicFlow() .step(CUSTOMER_ENTERS_TEXT) .as(customer).user(EntersText.class).system(displaysEnteredText()) .step(CUSTOMER_ENTERS_TEXT_AGAIN) .as(secondActor).user(EntersText.class).system(displaysEnteredText()) .build(); modelRunner.as(customer).run(model).reactTo(entersText()); modelRunner.as(secondActor).run(model).reactTo(entersText()); assertRecordedStepNames(CUSTOMER_ENTERS_TEXT, CUSTOMER_ENTERS_TEXT_AGAIN); }
@Test public void throwsExceptionIfSystemPartIsNotSpecified() { thrown.expect(MissingUseCaseStepPart.class); thrown.expectMessage(CUSTOMER_ENTERS_TEXT); modelBuilder.useCase(USE_CASE).basicFlow().step(CUSTOMER_ENTERS_TEXT).as(customer) .user(EntersText.class); Model model = modelBuilder.build(); modelRunner.as(customer).run(model); modelRunner.reactTo(entersText()); }
@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); }