Skip to content

Commit

Permalink
Updated docs
Browse files Browse the repository at this point in the history
  • Loading branch information
christianblos committed Nov 17, 2021
1 parent d71f3d6 commit a20f433
Showing 1 changed file with 57 additions and 26 deletions.
83 changes: 57 additions & 26 deletions docs/custom-scenario-builder.md
Original file line number Diff line number Diff line change
@@ -1,49 +1,55 @@
# Custom Scenario Builder

It is possible to create a custom `ScenarioBuilder` that is passed to all tests. For example if you want to reduce the
verbosity of tests, instead of
It is possible to create a custom `ScenarioBuilder` that is passed to all tests.

```java
@Test
public void test(ScenarioBuilder<GivenAppScenario> scenarioBuilder) {
scenarioBuilder.build(...);
}
```
## Example

you can write it like this:
In this example we make use of the [Spring Framework](https://spring.io/).
Our goal is to **execute the builder in a database transaction**.

```java
@Test
public void test(AppScenario appScenario) {
appScenario.build(...);
}
```

## Implementation

First, create your scenario builder that extends the original `ScenarioBuilder`:
First, we create a custom class that extends `ScenarioBuilder` and
wraps the `build()` and `cleanup()` method in a transaction:

```java
public class AppScenario extends ScenarioBuilder<GivenAppScenario> {

private final TransactionTemplate transactionTemplate;

public AppScenario(GivenScenarioFactory<GivenAppScenario> givenScenarioFactory,
Collection<ScenarioBuilderPart<GivenAppScenario>> scenarioBuilderParts) {
Collection<ScenarioBuilderPart<GivenAppScenario>> scenarioBuilderParts,
TransactionTemplate transactionTemplate) {
super(givenScenarioFactory, scenarioBuilderParts);
this.transactionTemplate = transactionTemplate;
}

@Override
public void build(Consumer<GivenAppScenario> scenarioConsumer) {
transactionTemplate.executeWithoutResult(status ->
super.build(scenarioConsumer));
}

@Override
public void cleanup() {
transactionTemplate.executeWithoutResult(status ->
super.cleanup());
}
}
```

Then you have to override the `createScenarioBuilder()` method in your Extension class:
Then we override the `createScenarioBuilder()` method in our Extension class.

```java
public class AppScenarioExtension extends ScenarioExtension<GivenAppScenario> {

@SuppressWarnings({"unchecked"})
@Override
protected Collection<ScenarioBuilderPart<GivenAppScenario>> getBuilderParts(ExtensionContext extensionContext) {
return List.of(
// ... your builder parts
);
ApplicationContext applicationContext = SpringExtension.getApplicationContext(extensionContext);

// return all ScenarioBuilderParts that are known by Spring
return applicationContext.getBeansOfType(ScenarioBuilderPart.class).values().stream()
.map(part -> (ScenarioBuilderPart<GivenAppScenario>) part)
.collect(Collectors.toList());
}

@Override
Expand All @@ -53,9 +59,34 @@ public class AppScenarioExtension extends ScenarioExtension<GivenAppScenario> {

@Override
protected ScenarioBuilder<GivenAppScenario> createScenarioBuilder(ExtensionContext extensionContext) {
// Create an instance of your custom Scenario Builder here
return new AppScenario(() -> createGivenScenario(extensionContext), getBuilderParts(extensionContext));
ApplicationContext applicationContext = SpringExtension.getApplicationContext(extensionContext);
TransactionTemplate transactionTemplate = applicationContext.getBean(TransactionTemplate.class);
return new AppScenario(() -> createGivenScenario(extensionContext), getBuilderParts(extensionContext), transactionTemplate);
}
}
```

Now, all tests execute the `build()` and `cleanup()` step in a transaction!

## Bonus

With a custom ScenarioBuilder we can now reference the new class in tests,
which also reduces the verbosity of the tests a bit.

Instead of

```java
@Test
public void test(ScenarioBuilder<GivenAppScenario> scenarioBuilder) {
scenarioBuilder.build(...);
}
```

We can do this:

```java
@Test
public void test(AppScenario appScenario) {
appScenario.build(...);
}
```

0 comments on commit a20f433

Please sign in to comment.