Search code examples
javaspring-bootmavencucumberjunit5

Junit5 Suite did not discover any tests (spring boot with cucumber setup)


Following this example, I'm trying to run a cucumber test in JUnit5, but the @Suite doesn't like me:

org.junit.platform.suite.engine.NoTestsDiscoveredException: Suite [org.ono.sprint.demo.CucumberRunnerTest] did not discover any tests

and I have fiddled with it and researched this for a the better part of a day now, would be extremely thankful if someone can give me hint in the right direction. It seems to be a problem on the a JUnit level since it doesn't even recognize the test class.

The test setup has an empty @Suite, @SpringBootTest class which appears to be configured by cucumber-specific annotations ...

package org.ono.sprint.demo;

import io.cucumber.spring.CucumberContextConfiguration;
import org.junit.platform.suite.api.ConfigurationParameter;
import org.junit.platform.suite.api.IncludeEngines;
import org.junit.platform.suite.api.SelectClasspathResource;
import org.junit.platform.suite.api.Suite;
import org.springframework.boot.test.context.SpringBootTest;

import static io.cucumber.junit.platform.engine.Constants.GLUE_PROPERTY_NAME;

@Suite
@IncludeEngines("cucumber")
@SelectClasspathResource("features")
@ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "org.ono.sprint.demo")
@CucumberContextConfiguration
@SpringBootTest
public class CucumberRunnerTest {
}

...to do the actual test described in a cucumber step definitions class, which is accompanied by a feature file. I don't think this is a cucumber problem at this stage, so I am ommitting the feature file):

package org.ono.sprint.demo;

import org.junit.jupiter.api.Assertions;

import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.web.client.RestTemplate;

import io.cucumber.java.en.When;

public class StepDefinitionsTest {

  @LocalServerPort
  private int port;

  private final RestTemplate restTemplate = new RestTemplate();

  @When("I request a greeting")
  public void i_request_a_greeting() {
    String greetingUrl = "http://localhost:" + port + "/greetings";

    String greeting = restTemplate.getForObject(greetingUrl, String.class);
    Assertions.assertEquals("Hello", greeting);
  }

}

also, the actual spring boot implementation is most trivial, so ommitted.

These are the maven dependencies:

<properties>
    <java.version>17</java.version>
    <junit-platform.version>1.9.1</junit-platform.version>
    <cucumber.version>7.10.1</cucumber.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-test</artifactId>
        <version>3.2.0</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>

    <dependency>
        <groupId>org.junit.platform</groupId>
        <artifactId>junit-platform-engine</artifactId>
        <version>${junit-platform.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.platform</groupId>
        <artifactId>junit-platform-suite-api</artifactId>
        <version>${junit-platform.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.platform</groupId>
        <artifactId>junit-platform-console-standalone</artifactId>
        <version>${junit-platform.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>io.cucumber</groupId>
        <artifactId>cucumber-spring</artifactId>
        <version>${cucumber.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>io.cucumber</groupId>
        <artifactId>cucumber-java</artifactId>
        <version>${cucumber.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>io.cucumber</groupId>
        <artifactId>cucumber-junit-platform-engine</artifactId>
        <version>${cucumber.version}</version>
        <scope>test</scope>
    </dependency>       
</dependencies>

and I am using the <artifactId>spring-boot-maven-plugin</artifactId>.


Solution

  • So, following M.P.Korstanjes advice, I got it to work. Most grateful, Thanks ! I believe it was a mix between lacking the junit-platform-suite dependency and, most importantly a wrong folder structure: this stuff expects to find the package folders under src/test/java to exactly replicate what is under src/main/java. Looks like the @SelectClassPathResource annotation did not work and falls back to default behavior. Also, the gherkin feature files apparently need to be under src/test/resources again, replicating the package folder structure from there. All this was not the case.
    So my sprint now looks like so:

    src/
      main/
        java/
          org/
            ono/
              sprint/
                 demo/
                   DemoApplication.java
                   HomeController.java
      test/
        java/
          org/
            ono/
              sprint/
                 demo/
                   SmokeTest.java
                   CucumberRunnerTest.java
        resource/
          org/
            ono/
              sprint/
                 demo/
                   helloworld.feature
    

    and the CucumberRunnerTest like so:

    package org.ono.sprint.demo;
    
    import io.cucumber.spring.CucumberContextConfiguration;
    import org.junit.platform.suite.api.ConfigurationParameter;
    import org.junit.platform.suite.api.IncludeEngines;
    import org.junit.platform.suite.api.SelectClasspathResource;
    import org.junit.platform.suite.api.Suite;
    import org.springframework.boot.test.context.SpringBootTest;
    
    import static io.cucumber.junit.platform.engine.Constants.GLUE_PROPERTY_NAME;
    
    @Suite
    @IncludeEngines("cucumber")
    @SelectClasspathResource("features")
    @ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "org.ono.sprint.demo")
    @CucumberContextConfiguration
    @SpringBootTest
    public class CucumberRunnerTest {
    }
    

    The dependencies are as follows. Note the dependency management section that was needed to resolve some of the cucumber deps.

    <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.junit</groupId>
                    <artifactId>junit-bom</artifactId>
                    <version>5.10.1</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <dependency>
                    <groupId>io.cucumber</groupId>
                    <artifactId>cucumber-bom</artifactId>
                    <version>7.14.1</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-test</artifactId>
                <version>3.2.0</version>
                <scope>test</scope>
            </dependency>
    
            <dependency>
                <groupId>io.cucumber</groupId>
                <artifactId>cucumber-java</artifactId>
                <scope>test</scope>
            </dependency>
    
            <dependency>
                <groupId>io.cucumber</groupId>
                <artifactId>cucumber-junit-platform-engine</artifactId>
                <scope>test</scope>
            </dependency>
    
            <dependency>
                <groupId>org.junit.platform</groupId>
                <artifactId>junit-platform-suite</artifactId>
                <scope>test</scope>
            </dependency>
    
            <dependency>
                <groupId>org.junit.jupiter</groupId>
                <artifactId>junit-jupiter</artifactId>
                <scope>test</scope>
            </dependency>
    
            <dependency>
                <groupId>io.cucumber</groupId>
                <artifactId>cucumber-spring</artifactId>
                <version>7.14.0</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>