25

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.

jakehschwartz
  • 945
  • 2
  • 12
  • 31
  • in your gradle configuration start spring-boot before you execute your cucumber test cases. Because your spring-boot app should be in a running condition before executing cucumber test cases. – Manmay Jun 05 '15 at 14:10
  • I don't know much groovy/gradle so could you give me an example? It starts itself for my integration tests so I figured I could use a similar mechanism. – jakehschwartz Jun 05 '15 at 15:23
  • have you tried `@IntegrationTest` . this will fire up your webserver etc as far as i know. i also use ` testCompile group: 'info.cukes', name: 'cucumber-junit', version:cucumberVersion` next to cucumber-spring. can you run your cucumber tests as junit tests in your ide? – Dude Jun 09 '15 at 12:33
  • Yes, I have cucumber-junit included. I cannot run my cucumber tests as junit tests from the IDE. Adding @IntegrationTest to my CucumberTest class and running that class as junit did not solve my problems. – jakehschwartz Jun 09 '15 at 13:44
  • have you tried configurating the context for the test? `@ContextConfiguration(classes = YourAppConfig.class, loader = SpringApplicationContextLoader.class)` together with the `@IntegrationTest ` can you run your application through your IDE or isnt that working either? – Dude Jun 11 '15 at 09:28
  • I have tried that, yes. I think it is working but there seems to be a bug in Spring Boot. I use @EnableAutoConfiguration(exclude = ...) but those auto configuration classes are not being excluded when I run the tests. I am waiting for verification from the Spring Boot team. – jakehschwartz Jun 11 '15 at 13:20
  • Try https://stackoverflow.com/a/44184693/343955 – adarshr May 25 '17 at 17:21

5 Answers5

13

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
Saikat
  • 8,190
  • 12
  • 69
  • 94
jakehschwartz
  • 945
  • 2
  • 12
  • 31
7

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
)
Nick Grealy
  • 18,859
  • 9
  • 84
  • 100
1

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;
...}
Joe Stepowski
  • 536
  • 5
  • 8
0

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 {
}
LucasP
  • 1,425
  • 12
  • 22
0

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);
     }
}
Community
  • 1
  • 1
hd1
  • 30,506
  • 4
  • 69
  • 81
  • So you are saying build the jar, run the jar and then run the tests in another thread? – jakehschwartz Jun 08 '15 at 16:24
  • I think I understand what you are saying but I don't think it will help me. I guess I should go back and edit my original question. I have no problem running cucumber tests. I need to be able to run them through gradle so that my CI server can pass my build. – jakehschwartz Jun 08 '15 at 16:31
  • @hd1 How you access this from static method? – deFreitas Feb 12 '16 at 14:52