I am writing a new app and trying to do BDD using cucumber and Spring Boot 1.4. Working code is as shown below:
@SpringBootApplication
public class Application {
@Bean
MyService myService() {
return new MyService();
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
public class MyService {}
Test code is as shown below:
@RunWith(Cucumber.class)
public class RunFeatures {}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = Application.class, loader = SpringApplicationContextLoader.class)
public class MyStepDef {
@Autowired
MyService myService;
@Given("^Some initial condition$")
public void appIsStarted() throws Throwable {
if (service == null) throw new Exception("Dependency not injected!");
System.out.println("App started");
}
@Then("^Nothing happens$")
public void thereShouldBeNoException() throws Throwable {
System.out.println("Test passed");
}
}
Feature file is as shown below:
Feature: Test Cucumber with spring
Scenario: First Scenario
Given Some initial condition
Then Nothing happens
When I run the above as is, all works well and dependency (MyService) is injected into MyStepDef with no issues.
If I replace this code:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = Application.class, loader = SpringApplicationContextLoader.class)
With the code below (New way to handle it in Spring Boot 1.4):
@RunWith(SpringRunner.class)
@SpringBootTest
Then the dependency (MyService) never gets injected. Am I missing something perhaps?
Thanks in advance for your help!!!
Prior to Spring Boot 1.4 you can use
From Spring Boot 1.4 onwards SpringApplicationContextLoader is deprecated so you should use SpringBootContextLoader.class instead
Really just adding @SpringBootTest (with an optional configuration class) should work on its own, but if you look at the code in cucumber.runtime.java.spring.SpringFactory method annotatedWithSupportedSpringRootTestAnnotations it's not checking for that annotation, which is why simply adding that annotation in conjunction with @SpringBootTest works.
Really the code in cucumber-spring needs to change. I'll see if I can raise an issue as in the Spring docs it states that SpringApplicationContextLoader should only be used if absolutely necessary.I'll try and raise an issue for this for the cucumber spring support.
So as it stands stripwire's answer using a combination of @SpringBootTest and @ContextConfiguration is the best workaround.
This is my configuration, you can try it
I've got it working in Spring Boot 1.5. I want to share the configuration with you:
pom.xml
Feature file
Cucumber hook
Abstract Spring Configuration
Glue
I had the same problem. The comment from above directed me to the solution
After adding the annotation
@ContextConfiguration
the tests are working as expected.So what i've got is the following...
I hope this helps you further
I got it working with Spring Boot 1.5.x and 2.0 and then wrote a blog post to try to clarify this since it's tricky.
First, even if it's obvious, you need to have the right dependencies included in your project (being
cucumber-spring
the important one here). For example, with Maven:Now, the important part to make it work, summarized:
@RunWith(Cucumber.class
.@Given
,@When
,@Then
, etc.).@SpringBootTest
,@RunWith(SpringRunner.class)
and any other configuration you need to run your test with Spring Boot. For instance, if you're implementing an integration test without mocking other layers, you should add thewebEnvironment
configuration and set it toRANDOM_PORT
orDEFINED_PORT
.See the diagram and the code skeleton below.
The entry point:
The Spring Boot base test class:
The step definitions class:
This is what you need to make DI work. For the full code example, just check my blog post or the code in GitHub.