Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@DirtiesContext tears context down after every cucumber test scenario, not class

Integration test executed by cucumber tends to leave behind context that causes problems with subsequent tests. Obvious solution appeared to be Spring's @DirtiesContext, but instead of tearing down the context after all the cucumber features have been run, it does this after each and every scenario, thus making the test execution time rather lengthy. Tried also with @TestExecutionListeners, but no luck.

@RunWith( SpringJUnit4ClassRunner.class )
@ContextConfiguration( classes = { MyApplication.class, MyTestComponent.class }, loader = SpringApplicationContextLoader.class )
@ActiveProfiles( { "test", "someotherprofile" } )
@DirtiesContext( classMode = DirtiesContext.ClassMode.AFTER_CLASS )
@WebIntegrationTest( randomPort = true )
public class StepDefs extends StepDefUtils {
    // givens, whens, thens

Am I trying to use DirtiesContext in an unsupported way?

like image 331
laur Avatar asked Jun 16 '16 15:06

laur


People also ask

Why scenario is skipped in Cucumber?

Cucumber skips all steps after a failed step by design. Once a step has failed, the test has failed and there should be no reason to perform the next steps. If you have a need to run the additional steps, likely your scenario is testing too many different things at once.

What is dirty context?

@DirtiesContext is a Spring testing annotation. It indicates the associated test or class modifies the ApplicationContext. It tells the testing framework to close and recreate the context for later tests. We can annotate a test method or an entire class.

What are the two files required to execute a Cucumber test scenario?

Following are the two files required to execute a Cucumber test scenario: Features. Step Definition.

What is use of @DirtiesContext?

@DirtiesContext may be used as a class-level and method-level annotation within the same class or class hierarchy.


1 Answers

As previous answer said the scenarios get compiled and run as separate classes stopping DirtiesContext from working and there are no per feature hooks in cucumber for same reason.

Workaround is to put tags in scenarios and have a class with hook detect these and conditionally dirty the context during the afterTestClass method. The tag lets you control when context gets dirtied for example if want each feature to have fresh context then mark last scenario with tag, or can have many time per feature as and when needed.

 public class CucumberFeatureDirtyContextTestExecutionListener extends AbstractTestExecutionListener{

   private static boolean dirtyContext = false;

   @After("@DirtyContextAfter")
   public void afterDirtyContext(){
     dirtyContext = true;
   }

   @Override public void afterTestClass(TestContext testContext) throws Exception {
     if (dirtyContext) {
       testContext.markApplicationContextDirty(HierarchyMode.EXHAUSTIVE);
       testContext.setAttribute(DependencyInjectionTestExecutionListener.REINJECT_DEPENDENCIES_ATTRIBUTE, TRUE);
       dirtyContext = false;
     }
   }
 }

Mark scenarios with tag

@DirtyContextAfter  
Scenario: My scenario

On steps class register the listener with spring

@TestExecutionListeners(listeners = {DependencyInjectionTestExecutionListener.class, CucumberFeatureDirtyContextTestExecutionListener.class})

Make sure the listener is in cucumber glue so after hook is registerd
Could not get it working on beforeClass as the context is already set up so have to do on afterClass.

like image 167
Phil Wray Avatar answered Oct 03 '22 02:10

Phil Wray