Skip to content

Commit

Permalink
[Spring] Document cucumber-glue scope (#1831)
Browse files Browse the repository at this point in the history
Closes: #1668
  • Loading branch information
mpkorstanje authored Dec 5, 2019
1 parent f64093d commit 9998d78
Showing 1 changed file with 52 additions and 35 deletions.
87 changes: 52 additions & 35 deletions spring/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ Add the `cucumber-spring` dependency to your `pom.xml`:

For your own classes:

* Add a `@Component` annotation to each of the classes cucumber-spring should manage.
* Add a `@Component` annotation to each of the classes `cucumber-spring` should
manage.
```java
package com.example.app;

Expand All @@ -41,7 +42,8 @@ public class Belly {
}
}
```
* Add the location of your classes to the `@ComponentScan` of your (test) configuration:
* Add the location of your classes to the `@ComponentScan` of your (test)
configuration:

```java
package com.example.app;
Expand All @@ -56,37 +58,14 @@ public class Config {
}
```

* Add `@DirtiesContext` to your test configuration if each scenario should have a fresh application context.
```java
package com.example.app;

import com.example.app.Config;
import cucumber.runtime.java.spring.beans.Belly;
import cucumber.runtime.java.spring.beans.BellyBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;

@ContextConfiguration(classes = { Config.class })
@DirtiesContext
public class SomeServiceSteps {

@Autowired
private Belly belly; // Each scenario have a new instance of Belly

[...]

}
```

For classes from other frameworks:

* You will have to explicitly register them as Beans in your (test) configuration:

```java
package com.example.app;

import other.framework.Class;
import com.example.other.framework.SomeOtherService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
Expand All @@ -102,17 +81,18 @@ public class TestConfig {
}
```

To make Cucumber aware of your test configuration you can annotate a single step definition with
`@ContextConfiguration`, `@ContextHierarchy` or `@BootstrapWith`. If you are using SpringBoot, you can annotate a
single step definition class with `@SpringBootTest(classes = TestConfig.class)`.
To make Cucumber aware of your test configuration you can annotate a single step
definition with `@ContextConfiguration`, `@ContextHierarchy` or
`@BootstrapWith`. If you are using SpringBoot, you can annotate a single step
definition class with `@SpringBootTest(classes = TestConfig.class)`.

For example:
```java
import com.example.app;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest(classes = TestConfig.class)
public class SomeServiceSteps {
public class SomeServiceStepDefinitions {

// the rest of your step definitions

Expand All @@ -127,7 +107,7 @@ import com.example.app;
import org.springframework.beans.factory.annotation.Autowired;

@SpringBootTest(classes = TestConfig.class)
public class SomeServiceSteps {
public class SomeServiceStepDefinitions {

@Autowired
SomeService someService;
Expand All @@ -139,7 +119,20 @@ public class SomeServiceSteps {
}
```

Changing a Spring bean's scope to `SCOPE_CUCUMBER_GLUE` will bound its lifecycle to the standard glue lifecycle.
### The Application Context & Cucumber Glue Scope

Cucumber Spring creates an application context. This application context is
shared between scenarios.

To prevent sharing state between scenarios, beans containing glue code
(i.e. step definitions, hooks, ect) are bound to the `cucumber-glue` scope.

The `cucumber-glue` scope starts prior to a scenario and end after a scenario.
Beans in this scope are created prior to a scenario execution and disposed at
the end of it.

Changing a Spring bean's scope to `SCOPE_CUCUMBER_GLUE` will bind its lifecycle
to the `cucumber-glue` scope.

```java
import org.springframework.stereotype.Component;
Expand All @@ -152,14 +145,38 @@ public class MyComponent {
}
```

If your tests do dirty the application context you can add `@DirtiesContext` to
your test configuration.

```java
package com.example.app;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest(classes = TestConfig.class)
@DirtiesContext
public class SomeServiceStepDefinitions {

@Autowired
private Belly belly; // Each scenario have a new instance of Belly

[...]

}
```

### XML Configuration

If you are using xml based configuration, you can to register the beans in a `cucumber.xml` file:
If you are using xml based configuration, you can to register the beans in a
`cucumber.xml` file:

```xml
<bean class="com.example.app.MyService"/>
<bean class="com.example.lib.SomeOtherService"/>
```

Annotate a single step definition class with `@ContextConfiguration("classpath:cucumber.xml")`
Annotate a single step definition class with
`@ContextConfiguration("classpath:cucumber.xml")`

0 comments on commit 9998d78

Please sign in to comment.