How to populate database only once before @Test methods in spring test?

前端 未结 5 1406
小蘑菇
小蘑菇 2020-12-08 08:00

My next problem testing spring service layer with junit4 is: How to call script that populates database only once before all @Test methods: I want to execute this once befor

相关标签:
5条回答
  • 2020-12-08 08:41

    Example based on Mike Adlers example but for JUnit 5 and with use of ResourceDatabasePopulator mentioned by Tugdual.

    Test classes is created once for every test method. So if you want to populate only once you need to handle that somehow. Here it is done with a static variable.

    @Autowired
    private DataSource dataSource;
    
    private static boolean isInitialized;
    
    @BeforeEach // JUnit 5
    void initDatabase() {
      if(!isInitialized) { // init only once
        ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
        populator.addScript(new ClassPathResource("/sql/myscript.sql")));
        populator.execute(dataSource);
        isInitialized = true;
      }
    }
    

    Edited: A Better solution.

    Junit 5 provides @BeforeAll as mentioned by others and should be the correct answer

    @Autowired
    private DataSource dataSource;
    
    @BeforeAll // JUnit 5
    void initDatabase() {
      ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
      populator.addScript(new ClassPathResource("/sql/myscript.sql")));
      populator.execute(dataSource);
    }
    
    0 讨论(0)
  • 2020-12-08 08:48

    You can use JUnit 5's @BeforeAll annotation

    0 讨论(0)
  • 2020-12-08 08:50

    Use Springs Embedded Database Support

    <jdbc:embedded-database id="dataSource">
        <jdbc:script location="classpath:myScript.sql"/>
        <jdbc:script location="classpath:otherScript.sql"/>
    </jdbc:embedded-database>
    

    or Springs Initialize Database Support

    <jdbc:initialize-database data-source="dataSource">
        <jdbc:script location="classpath:myScript.sql"/>
        <jdbc:script location="classpath:otherScript.sql"/>
    </jdbc:initialize-database>
    

    @See http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/jdbc.html#jdbc-embedded-database-support

    0 讨论(0)
  • 2020-12-08 09:02

    Building on Alfredos answer, this is a way to inject database information without calling the embedded database's default script. For instance, this may be useful when you want to automagically build the DDL for you - at least in tests.

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration({"/applicationContext.xml"})
    public class TestClass {
    
        @Autowired
        private ApplicationContext ctx;
    
        private JdbcTemplate template;
    
        @Autowired
        public void setDataSource(DataSource dataSource) {
           template = new JdbcTemplate(dataSource);
        }
    
        private static boolean isInitialized = false;
    
        @Before
        public void runOnce() {
            if (isInitialized) return;
            System.out.println("Initializing database");
    
            String script = "classpath:script.sql"; 
            Resource resource = ctx.getResource(script);
            JdbcTestUtils.executeSqlScript(template, resource, true);            
            isInitialized = true;
        }
    }
    

    This way, the runOnce() method is called once and only once for the test run. If you make isInitialized an instance field (non-static), the method will be called before every test. This way you can drop/repopulate the tables, if necessary, before every test run.

    Note that this is still a rather quick-and-dirty solution and the sensible way to handle the database is in accordance with Ralph's answer.

    0 讨论(0)
  • 2020-12-08 09:04

    in case you are spring boot, u can mention multiple scripts to launch before tests via

    spring.datasource.data=classpath:accounts.sql, classpath:books.sql, classpath:reviews.sql
    
    0 讨论(0)
提交回复
热议问题