jakehschwartz
jakehschwartz

Reputation: 1005

Cucumber Test a Spring Boot Application

Does anyone know where I can find a sample application where Cucumber is used to test a Spring Boot application through Gradle? I can run the tests fine starting the server on the cmd line and using my IDE, but I need to be able to run them all programmatically on the CI server. I saw the answer on here but that solution did not work for me, most likely because I have multiple step def files.

Here is my setup

build.grade (Mentioned in the other question)

testCompile ("org.springframework.boot:spring-boot-starter-test",
    ...
    "info.cukes:cucumber-spring:${cucumberVersion}")

CucumberTest.java

@RunWith(Cucumber.class)
@CucumberOptions(format = "pretty", features = "src/test/resources")
public class CucumberTest{
}

AbstractSpringTest.java (Extended by all the StepDef files)

@SpringApplicationConfiguration(classes = Application.class)
@RunWith(SpringJUnit4ClassRunner.class)
@Ignore
public abstract class AbstractSpringTest
{ ... }

It's not doing the correct thing on start up because its 1. trying to initialize my step def files and 2. My application is not started and the cucumber tests cannot make a connection.

Thanks.

EDIT: Or if someone can tell me how to start and stop the application using gradle, that would be acceptable as well.

Upvotes: 26

Views: 36579

Answers (5)

jakehschwartz
jakehschwartz

Reputation: 1005

I have solved the issue with some help from this question.

Here is the repository with the answer: https://github.com/jakehschwartz/spring-boot-cucumber-example

In short, the AbstractSpringTest class needs to have the following annotations:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = DemoApplication.class, loader = SpringApplicationContextLoader.class)
@WebAppConfiguration
@IntegrationTest

Upvotes: 13

Nick Grealy
Nick Grealy

Reputation: 25952

I had a similar symptom, my cucumber wouldn't start up the Spring context...

Turns out I had missed (one of) the following dependencies:

build.gradle

testCompile "info.cukes:cucumber-junit:1.2.4"
testCompile "info.cukes:cucumber-java:1.2.4"
testCompile "info.cukes:cucumber-spring:1.2.4"

StepDefs.java

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
        loader = SpringApplicationContextLoader.class,
        classes = Application.class
)
@WebIntegrationTest(randomPort = true)
public class StepDefs {

    @Value("${local.server.port}")
    int port;

}

Update: SpringBoot 1.5.1

@ContextConfiguration(
        loader = SpringBootContextLoader.class,
        classes = Application.class
)

Upvotes: 7

Joe Stepowski
Joe Stepowski

Reputation: 666

Further to @jakehschwartz, if you want the web app to start on a random available port, AbstractSpringTest needs:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = Application.class, loader = SpringApplicationContextLoader.class)
@WebIntegrationTest({"server.port=0"})
public abstract class AbstractSpringTest {

        @Value("${local.server.port}")
        protected int serverPort;
...}

Upvotes: 1

hd1
hd1

Reputation: 34677

First, you'll need to ensure that you have applied spring-boot in gradle. Invoke gradle build which will produce a runnable jar. Instead of having your manifest call for the Spring class as your main, have a wrapper that starts it in a thread, waits for it to settle down and runs Cucumber:

@RunWith(Cucumber.class)
public class LucasePsCucumberTest implements Runnable {
    public static void main(String[] args) {
        Thread t = new Thread(this);
        t.start();
        // wait for t
        cucumber.api.cli.Main(null);
     }
}

Upvotes: 0

LucasP
LucasP

Reputation: 1715

I did something like this to get Spring to work with JUnit parameterized tests. It should be the same concept for Cucumber, but I haven't tried it. I was using XML configuration, so that might make a difference.

RunWithSpringJUnit4

public abstract class RunWithSpringJUnit4 {

    private TestContextManager testContextManager;

    public RunWithSpringJUnit4() {
        try {
            this.testContextManager = new TestContextManager(getClass());
            this.testContextManager.prepareTestInstance(this);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

CucumberTest

@RunWith(Cucumber.class)
@CucumberOptions(format = "pretty", features = "src/test/resources")
public class CucumberTest extends RunWithSpringJUnit4 {
}

Upvotes: 0

Related Questions