简体   繁体   English

Spring 测试 @SqlGroup 和 @PostConstruct on bean

[英]Spring Test @SqlGroup with @PostConstruct on bean

I'm trying to execute some SQL statements with @SqlGroup before running some integration tests using Spring 5, Junit4.11 and JDK8.在使用Spring 5、Junit4.11 和 JDK8运行一些集成测试之前,我试图用 @SqlGroup 执行一些 SQL 语句

Everything was working flawless until today, when I added some initial configuration on my "ConfigurationComponent" bean, with the annotation @PostConstruct.直到今天,当我在“ConfigurationComponent”bean 上添加了一些初始配置时,一切都完美无缺,并带有 @PostConstruct 注释。

As @PostConstruct method calls a database-dependent bean, the test fails, because hiberante (thus the database) can't find the preloaded schema.当@PostConstruct 方法调用依赖于数据库的 bean 时,测试失败,因为 hiberante(因此数据库)找不到预加载的模式。

As I investigated, I found that statements put in @SqlGroup will execute after ApplicationContext initialization, so the @PostConstruct is executed before the schema is loaded.经过调查,发现@SqlGroup 中的语句会在ApplicationContext 初始化之后执行,所以@PostConstruct 在schema 加载之前执行。

Here is my integration test abstract class.这是我的集成测试抽象类。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:application-context-test.xml" })
@Transactional
@Rollback(true)
@SqlGroup({
        @Sql(executionPhase = ExecutionPhase.BEFORE_TEST_METHOD, scripts = {
                "classpath:db_config.sql",
                "classpath:consultas/setup_esquema_0.1.sql",
                "classpath:db_datos_iniciales.sql"}),
        @Sql(executionPhase = ExecutionPhase.AFTER_TEST_METHOD, scripts = "classpath:db_teardown.sql") })
public abstract class AbstractServiceTest {

    @BeforeClass
    public static void setUpBeforeClass() throws Exception {

    }

    @AfterClass
    public static void tearDownAfterClass() throws Exception {
    }

    @Before
    public abstract void setUp() throws Exception;

    @After
    public abstract void tearDown() throws Exception;

    public static Long randomId() {
        return new Long(Math.round(Math.random() * 1000));
    }

}

The offending bean冒犯的豆

@Configuration
public class ConfigurationComponent {

    @Autowired
    Resources resources; // resources are retrieved from database.

    @PostConstruct
    public void startUp() throws VariableGlobalInexistenteException {
        Config.environment = resources
                .getWsaaEnv();
        Config.validation = resources
                .getWsaaEnvValidation();
    }

}

I can't find a way to overcome this issue using @SqlGroup.我找不到使用@SqlGroup 解决此问题的方法。 Is there any solution, a way to alter the lifecycle and execute the sql statements first?.有没有解决方案,一种改变生命周期并首先执行sql语句的方法? As you can see, I'm using ExecutionPhase.BEFORE_TEST_METHOD , there is no explicit configuration for this case, like "ExecutionPhase.BEFORE_SETUP".如您所见,我使用的是ExecutionPhase.BEFORE_TEST_METHOD ,这种情况没有明确的配置,例如“ExecutionPhase.BEFORE_SETUP”。


Update 09-07-2018 - Looks like there is no way of achieving this using @Sql: 2018 年 9 月 7 日更新 - 使用 @Sql 似乎无法实现此目的:

Both @Sql and the calling of @PostConstruct are handled by Spring Framework rather than Spring Boot. @Sql 和 @PostConstruct 的调用都由 Spring Framework 处理,而不是 Spring Boot。 Also, I believe this is working as designed.另外,我相信这是按设计工作的。 The default execution phase for @Sql is BEFORE_TEST_METHOD (the other option is AFTER_TEST_METHOD). @Sql 的默认执行阶段是 BEFORE_TEST_METHOD(另一个选项是 AFTER_TEST_METHOD)。 The application context is refreshed, and therefore @PostConstruct is called, once for the whole test class (in fact it could be once for multiple test classes if they share the same configuration) which happens before individual test methods are called.应用程序上下文被刷新,因此 @PostConstruct 被调用一次,整个测试类(实际上,如果多个测试类共享相同的配置,它可能是一次),这发生在调用单个测试方法之前。 In other words, you cannot use @Sql as a means of preparing the database for calls that are made in @PostConstruct.换句话说,您不能使用@Sql 作为为@PostConstruct 中进行的调用准备数据库的方法。

Github @PostConstruct executed before @Sql Github @PostConstruct 在 @Sql 之前执行

I've managed to find a workaround.我设法找到了解决方法。 As the latest update stated, there is no way of achieving the desired behavior using @SqlGroup.正如最新更新所述,使用@SqlGroup 无法实现所需的行为。 I've had to use the following approach, using @BeforeClass and @AfterClass:我不得不使用以下方法,使用@BeforeClass 和@AfterClass:

@BeforeClass
public static void setUpBeforeClass() throws Exception {

    DriverManagerDataSource dataSource = getDataSource();
    Connection conn = dataSource.getConnection();
    ScriptUtils.executeSqlScript(conn, new ClassPathResource("db_config.sql"));
    ScriptUtils.executeSqlScript(conn, new ClassPathResource("consultas/setup_schema"));
    ScriptUtils.executeSqlScript(conn, new ClassPathResource("db_init.sql"));
    JdbcUtils.closeConnection(conn);

}

@AfterClass
public static void tearDownAfterClass() throws Exception {
    Connection conn = getDataSource().getConnection();
    ScriptUtils.executeSqlScript(conn, new ClassPathResource(
            "db_teardown.sql"));
    JdbcUtils.closeConnection(conn);
}

private static DriverManagerDataSource getDataSource() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setUrl(url);
    dataSource.setUsername(username);
    dataSource.setPassword(password);
    dataSource.setDriverClassName(driver);
    return dataSource;
}

All @SqlGroup annotations were removed.删除了所有@SqlGroup 注释。 This methodology is quite clean, as ScriptUtils doesn't need much dependencies to run.这种方法非常干净,因为 ScriptUtils 不需要太多的依赖来运行。

Another workaround would be implementing CommandLineRunner.另一种解决方法是实施 CommandLineRunner。

@Component
public class ConfigurationInitRunner implements CommandLineRunner {

    @Autowired
    Resources resources; // resources are retrieved from database.

    @Override
    public void run(String... strings) throws Exception {
        Config.environment = resources.getWsaaEnv();
        Config.validation = resources.getWsaaEnvValidation();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM