Search code examples
javacucumbercdicucumber-jvmcucumber-junit

Cucumber CDI injection does not work with beans in src/main/java


I have a JEE application in a maven project using JUnit and Cucumber to test my code. The application is using CDI with weld-se in test scope.

I have created a simple feature file src/test/resources/specification/first.feature

Scenario: Identified user
  Given I am user A

Then I created the corresponding cucumber step:

public class FirstSteps {

@Inject
UserService userService;

@Given("^I am user A$")
public void i_am_user_A() throws Throwable {
    User user = User.new().withName("user A").create();
    assertThat(userService.getActualUser()).isEqualTo(user);
}

}

User Service is an Interface with one trivial implementation:

public interface UserService {
    User getActualUser();
}

public class FakeUserService implements UserService {

    @Override
    public User getActualUser() {
        return User.new().withName("user A").create();
    }

}

There are empty beans.xml files in src/main/resources/META-INF and src/test/resources/META-INF.

The step is located in src/test/resources, the service interface and its implementation in src/main/java.

And here is the JUnit-Test for it:

@RunWith(Cucumber.class)
@CucumberOptions(
    features = {"classpath:specifikation"},
    glue = {"mypackage"})
public final class CucumberTests {
}

The step is found by cucumber and gets executed. But CDI does not work:

Exception in thread "main" org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type UserService with qualifiers @Default at injection point [BackedAnnotatedField] @Inject mypackage.FirstSteps.userService

I have found this issue on github for cucumber. But the solution does not work for me. I already have two empty beans.xml files in src/main/resources/META-INF and src/test/resources/META-INF.

It seems like the weld container creates a context for src/test only and everything in src/main does not belong to it. When I move the service interface and implementation to src/test/java it works...

Is there a way to reference beans in src/main from src/test?

EDIT: corrected location of the service interface


Solution

  • Assuming that your step is located in src/test/java and your service (interface) is located in src/main/java and not in src/(test|main)/resources (typo?), your setup should work.

    Maybe check the following:

    1. Ensure that your src/main/java and src/test/java folders are on the same classpath.
    2. Assuming that you are using a current version of Weld which is CDI >1.1 compliant, ensure that both folders are explicit bean archives.
    3. Ensure your beans.xml files are literally empty or have bean-discovery-mode set to all.

    If that does not work either, try to annotate your FakeUserService.