/** * 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 the model runner to work) * @return the created system part of this step */ StepSystemPart<ModelRunner> system(Consumer<ModelRunner> autonomousSystemReaction) { StepSystemPart<ModelRunner> systemPart = user(ModelRunner.class).system(autonomousSystemReaction); return systemPart; }
@Test public void actorsCanBeReusedInUseCase() { UseCasePart useCasePart = modelBuilder.useCase(USE_CASE); Model model = useCasePart.basicFlow() .step(CUSTOMER_ENTERS_TEXT).as(customer).user(EntersText.class).system(displaysEnteredText()) .step(CUSTOMER_ENTERS_TEXT_AGAIN).as(customer).user(EntersText.class).system(displaysEnteredText()) .build(); Collection<Step> steps = model.getSteps(); assertEquals(2, steps.size()); Iterator<Step> stepsIt = steps.iterator(); Actor actor1 = stepsIt.next().getActors()[0]; Actor actor2 = stepsIt.next().getActors()[0]; assertTrue(actor1 == actor2); assertEquals(customer, actor1); }
@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 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 onlyStepWithRightActorInDifferentFlowReacts() { Model model = modelBuilder .useCase(USE_CASE) .basicFlow() .step(CUSTOMER_ENTERS_TEXT) .as(secondActor).user(EntersText.class).system(throwsRuntimeException()) .flow(ALTERNATIVE_FLOW).condition(this::textIsNotAvailable) .step(CUSTOMER_ENTERS_TEXT_AGAIN) .as(customer).user(EntersText.class).system(displaysEnteredText()) .build(); modelRunner.as(customer).run(model); Optional<Step> lastStepRun = modelRunner.reactTo(entersText()); assertEquals(CUSTOMER_ENTERS_TEXT_AGAIN, lastStepRun.get().getName()); }
@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 stepWithWrongActorInDifferentFlowDoesNotReact() { Model model = modelBuilder .useCase(USE_CASE) .basicFlow() .step(CUSTOMER_ENTERS_TEXT) .as(customer).user(EntersText.class).system(displaysEnteredText()) .step(CUSTOMER_ENTERS_ALTERNATIVE_TEXT) .as(customer).user(EntersText.class).system(displaysEnteredText()) .flow(ALTERNATIVE_FLOW).insteadOf(CUSTOMER_ENTERS_ALTERNATIVE_TEXT) .step(THIS_STEP_SHOULD_BE_SKIPPED) .as(secondActor).user(EntersText.class).system(throwsRuntimeException()) .build(); modelRunner.as(customer).run(model).reactTo(entersText(), entersText()); assertEquals(CUSTOMER_ENTERS_ALTERNATIVE_TEXT, latestStepName()); }
@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 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 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 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 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 createsSingleActorWithSingleUseCaseStep() { 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.getName()); List<Step> steps = customerActor.getStepsOf(useCasePart.getUseCase()); Step step = steps.get(0); assertEquals(CUSTOMER_ENTERS_TEXT, step.getName()); assertEquals(CUSTOMER_ENTERS_TEXT, step.toString()); assertEquals(USE_CASE, step.getUseCase().getName()); assertEquals(customer, step.getActors()[0]); }