Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
926 views
in Technique[技术] by (71.8m points)

spring - How to execute @Sql before a @Before method

I'm trying to combine the follow annotations:

org.springframework.test.context.jdbc.Sql and org.junit.Before

Like the follow code:

@Test
@Sql(scripts = "dml-parametro.sql")
public void testData(){
    Iterable<Parametro> parametros = parametroService.findAll();
    List<Parametro> parametrosList = Lists.newArrayList(parametros);

    Assert.assertThat(parametrosList.size(), Is.is(1));
}

@Before
public void beforeMethod() {
    JdbcTestUtils.deleteFromTables(jdbcTemplate, "PARAMETRO");
}

The code in the method @Before is running after then the script "dml-parametro.sql" in the @Sql annotation.

Is it right to do this?

For solution this, I'm using @After in place than @Before, but I'd like to cdelete tables before the test execution, not after.

I wouldn't like to use @SqlConfig. I'm not using transacional scope on test level, so i need to clean my tables in every test method. If every test method need to clean tables, i would like to do this in @Before method. I wouldn't like to do this in every test method with @SqlConfig. I think the behavior of @Sql to be execute before than @Before is wrong.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

By default, any SQL scripts executed via @Sql will be executed before any @Before methods. So the behavior you are experiencing is correct, but you can change the execution phase via the executionPhase attribute in @Sql (see example below).

If you want to execute multiple scripts, that is also possible via @Sql.

So if you have a clean-up script named clean-parametro.sql that deletes from the PARAMETRO table, you could annotate your test method like the following (instead of invoking JdbcTestUtils.deleteFromTables() in your @Before method).

@Test
@Sql({"dml-parametro.sql", "clean-parametro.sql"})
public void test() { /* ... */ }

Of course, if dml-parametro.sql inserts values into the PARAMETRO table, then it likely does not make sense to immediately delete those values in the clean-up script.

Please note that @Sql and @SqlConfig provide multiple levels of configuration for script execution.

For example, if you want to create tables before your test and clean up after your test, you could do something like this on Java 8:

@Test
@Sql("create-tables.sql")
@Sql(scripts = "clean-up.sql", executionPhase = AFTER_TEST_METHOD)
public void test() { /* ... */ }

Or use @SqlGroup as a container on Java 6 or Java 7:

@Test
@SqlGroup({
    @Sql("create-tables.sql"),
    @Sql(scripts = "clean-up.sql", executionPhase = AFTER_TEST_METHOD)
})
public void test() { /* ... */ }

If your tests are @Transactional and you'd like to clean up committed database state, you can instruct Spring to execute your clean-up SQL script in a new transaction like this:

@Test
@Sql("insert-test-data.sql")
@Sql(
  scripts = "clean-up.sql",
  executionPhase = AFTER_TEST_METHOD,
  config = @SqlConfig(transactionMode = ISOLATED)
)
public void test() { /* ... */ }

I hope this clarifies things for you!

Cheers,

Sam (author of the Spring TestContext Framework)


Notes:

  • AFTER_TEST_METHOD is statically imported from ExecutionPhase
  • ISOLATED is statically imported from TransactionMode

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...