question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Use TestContextManager in cucumber-spring

See original GitHub issue

Summary

Support TestContextManager in cucumber-spring.

Expected Behavior

When using cucumber-spring @MockBean (and other annotations) should just work.

public class Example {

    @MockBean
    private User object;

    @Given("there is a User")
    public void there_is_a_User() {
        when(object.toString()).thenReturn("I've been mocked");
    }

    @Then("the User is mocked")
    public void the_user_is_mocked() throws Exception {
        assertThat(object.toString(), equalTo("I've been mocked"));
    }
}

Current Behavior

It is currently possible to use @Autowired e.g.:

public class Example {

    @Autowired
    private User object;

    @Then("the user is real")
    public void the_user_is_mocked() throws Exception {
        assertThat(object.toString(), equalTo("I am real"));
    }
}

But fields annotated with@MockBean are not mocked, the example fails with a null pointer exception.

Possible Solution

The causes of failure are two fold:

  1. There is no spring context declared (ContextConfiguration, BootstrapWith, ect) so the SpringFactory falls back to some minimal default. This can be resolved by adding @SpringBootTest to the step definition.

  2. The SpringFactory does not call

  • TestContextManager.beforeTestClass()
  • TestContextManager.prepareTestInstance().
  • TestContextManager.beforeTestMethod()
  • TestContextManager.beforeTestExecution()
  • TestContextManager.afterTestExecution()
  • TestContextManager.afterTestMethod()
  • TestContextManager.afterTestClass()

Instead step definitions are registered as beans in the Spring context. This had the advantage that step definitions can be auto wired into each other and constructor dependency injection just works. However it also puts the step definitions into the spring context which complicates things.

Given that step definitions calling each other is not a best practice I would not mind step definitions were no longer part of the spring context and instead treated as test instances (see SpringJUnit4ClassRunner.createTest). Any dependency injection would have to be done via @Autowired.

So to implement this properly the following would have to be done:

  • Require that all step definitions created have an empty constructor.
  • Map the life-cycle methods of the TestContextManager to that of the ObjectFactory.
  • Fail when there is no Spring context declared instead of creating a default.

Your Environment

  • Version used: cucumber-spring:4.0.0

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:2
  • Comments:18 (12 by maintainers)

github_iconTop GitHub Comments

1reaction
pprotascommented, Dec 16, 2021

Is there an update on this? I’ve been using the workaround mentioned above, but i would like to use @MockBean in my stepdef classes for better readability of the code.

1reaction
mpkorstanjecommented, Jun 4, 2020

If you’re using 6.0.0-RC2 you could use something like this:

@CucumberContextConfiguration
@SpringBootTest(classes = TestConfig.class)
public class CucumberSpringConfiguration {

  @MockBean
  public MyService service;

}

The class annotated with @CucumberContextConfiguration is passed to springs TestContextManager and subject to the same processing the class would be in JUnit. So this should result in the application context being created with a mocked MyService bean.

You’ll have to figure out the edgecase yourself.

Read more comments on GitHub >

github_iconTop Results From Across the Web

CucumberTestContextManager.getBeanFactory - Java
How to use. getBeanFactory. method. in. cucumber.runtime.java.spring.CucumberTestContextManager. Best Java code snippets using cucumber.runtime.
Read more >
SpringFactory (Cucumber-JVM: Spring 6.8.0 API) - javadoc.io
SpringFactory uses Springs TestContextManager framework to manage the spring context. The class annotated with CucumberContextConfiguration will be use to ...
Read more >
Cucumber Test a Spring Boot Application - java - Stack Overflow
I have solved the issue with some help from this question. Here is the repository with the answer: ...
Read more >
Developers - Use TestContextManager in cucumber-spring -
Summary. Support TestContextManager in cucumber-spring . Expected Behavior. When using cucumber-spring @MockBean (and other annotations) should just work.
Read more >
cucumber.runtime.java.spring.SpringFactory Maven / Gradle / Ivy
It uses TestContextManager to manage the spring context. * Configuration via: @ContextConfiguration or @ContextHierarcy * At least on step definition class ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found