Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring & Cucumber integration: @Sql import didn't execute

I need to integrate the cucumber with spring in a practice. But I can't import some test data with spring's @Sql annotation. However the other integration tests that not use cucumber works fine. I didn't find why? The cucumber runner:

@RunWith(Cucumber.class)
@CucumberOptions(features={"classpath:features/"})
public class CucumberIT {

}

And the step defination:

@RunWith(SpringRunner.class)
@ContextConfiguration(classes={DevDbConfig.class})
@Sql("classpath:test-reader-data.sql")
@Transactional
@ActiveProfiles("dev")
public class StepDefines {

  @Autowired
  ReaderService readerService;

  Reader reader;

  @Given("^a user with name Lily$")
  public void a_user_with_name_Lily() throws Throwable {
    reader = readerService.findByName("Lily"); // reader is null here!
  }

  @Given("^this user Lily exists$")
  public void this_user_Lily_exists() throws Throwable {
      assertThat(reader, notNullValue());
  }

  @Then("^Lily's info should be returned$")
  public void lily_s_info_should_be_returned() throws Throwable {
      assertThat(reader.getName(), is("Lily"));
  }

}

But the following testing code can import the testing data normally:

@RunWith(SpringRunner.class)
@ContextConfiguration(classes={DevDbConfig.class})
@Sql("classpath:test-reader-data.sql")
@Transactional
@ActiveProfiles("dev")
public class ReaderServiceTest {

  @Autowired
  ReaderService readerService;

  @Autowired
  EntityManager entityManager;

  @Test
  public void testQueryByIdAndShouldNotReturnNull() {    
    Reader reader = readerService.findByName("Lily");
    assertThat(reader, notNullValue()); // reader is not null!
  }

}

Thanks!

like image 232
Guisong He Avatar asked Feb 26 '26 17:02

Guisong He


1 Answers

The @Sql will be executed by SqlScriptsTestExecutionListener. The Spring SpringJUnit4ClassRunner will register all of the TestExecutionListeners.

From theSqlScriptsTestExecutionListenerjava doc, it says:

Scripts and inlined statements will be executed before or after execution of the corresponding test method, depending on the configured value of the executionPhase flag.

So a class level @Sql is equivalent to all @Testmethods with individual @Sqlannotation.

However, when cucumber is running, it won't execute any @Test method and the @Sql doesn't have chance to be executed.

Finally, I have to do it myself:

  @Autowired
  DataSource ds;

  @Given("^a user with name Lily$")
  public void a_user_with_name_Lily() throws Throwable {
    ScriptUtils.executeSqlScript(ds.getConnection(), new ClassPathResource("test-reader-data.sql"));
    reader = readerService.findByName("Lily");
  }

  @Given("^this user Lily exists$")
  public void this_user_Lily_exists() throws Throwable {
    assertThat(reader, notNullValue());
  }

  @Then("^Lily's info should be returned$")
  public void lily_s_info_should_be_returned() throws Throwable {
    assertThat(reader.getName(), is("Lily"));
  }
like image 59
Guisong He Avatar answered Mar 02 '26 15:03

Guisong He



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!