Mihai238
Mihai238

Reputation: 1137

@SQL one time per class

I'm writing some integration test using spring framework. I have different SQL scripts for different integration test classes. Something like this:

@ContextConfiguration(classes = ...)
@Sql("classpath:sportCenter-test.sql")
public class SportCenterResourceIT {
    ...
}

Everything works perfectly except for the fact that the SQL script is executed before each test, instead of one time per class. I have already searched for some time the spring documentation but I was not able to find something related to such an option.

Could anybody give me an hint?

Upvotes: 16

Views: 10111

Answers (5)

Ameur fahd
Ameur fahd

Reputation: 21

You can create an empty static method annotated with @BeforeAll and @Sql("classpath:sportCenter-test.sql")

@BeforeAll
@Sql("classpath:sportCenter-test.sql") 
public static void initSql() {
    
}

Upvotes: -4

Khyati Elhance
Khyati Elhance

Reputation: 748

If we want to execute sql script one time per class, we can execute the script in setup method and set flag to true once the script is executed for one method so it does not execute again. ` @Autowired private DataSource database;

private static boolean dataLoaded = false;

@Before
public void setup() throws SQLException {
    if(!dataLoaded) {
        try (Connection con = database.getConnection()) {
            ScriptUtils.executeSqlScript(con, new ClassPathResource("path_to_script.sql"));
            dataLoaded = true;
        }
    }
}`

Upvotes: 4

buderu
buderu

Reputation: 445

I solved my problem by putting the sql script in the src/test/resources folder with the name data.sql. This file is executed once at startup of each integration test. For this to work, you need to remove the @Sql annotation.

Upvotes: 1

tatka
tatka

Reputation: 331

I use this way to resolve the problem:

@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
@Sql("classpath:sql/DataForRouteTesting.sql")
public class MyTest {}

Scripts are executed every time, but there are not conflict primary key.

Upvotes: 10

mskluev
mskluev

Reputation: 301

Adding the org.springframework.transaction.annotation.Transactional annotation at the class level will prevent any changes from @Sql scripts from persisting between tests. So your code becomes:

@ContextConfiguration(classes = ...)
@Sql("classpath:sportCenter-test.sql")
@Transactional
public class SportCenterResourceIT {
    ...
}

This combination will result in the following:

  1. Your @Sql script will run before each test
  2. The test itself will run
  3. Any database changes from steps 1 or 2 will be reverted at the end of each test

Upvotes: 10

Related Questions