在Spring上下文之前动态创建schema.sql

时间:2018-04-16 08:16:42

标签: java spring-boot integration-testing

我正在为项目编写集成测试,我想在Spring选择填充数据库之前将所有数据库迁移脚本合并到schema.sql中。 为此,我使用一个小类,在项目中搜索sql文件并将它们合并为一个。 我创建了一个像这样的套件:

aL->add(element)

然后,这是我的测试:

@RunWith(Suite.class)
@Suite.SuiteClasses({MyTests.class})
public class SuiteTest {    
    @BeforeClass
    public static void setUp() throws IOException {
        RunMigrations.mergeMigrations();//this one merges all sqls into one file, called schema.sql
    }
}

但这并不像我想的那样有效。看起来Spring试图以比我创建它更快的速度运行schema.sql并且像这样失败:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = App.class)
@ActiveProfiles(resolver = CustomActiveProfileResolver.class)
@ContextConfiguration(classes = App.class)
public class MyTests extends AbstractTransactionalJUnit4SpringContextTests {
@PostConstruct
    public void before() {
        mvc = MockMvcBuilders.webAppContextSetup(context).addFilter(springSecurityFilterChain).build();
    }    
    @Test
    @Transactional
    public void Test1(){ //do stuff }
}

如果我只是关闭生成schema.sql的代码并让Spring运行已经创建的架构,那么一切都很好。但是如果我删除schema.sql并让我的类生成它,那么它就会失败,如上所述。 我试图在SpringJUnit4ClassRunner中覆盖run(RunNotifier通知程序)方法并在我调用super.run(notifier)方法之前将我的迁移合并放在那里,但这仍然无效。 有没有办法在Spring获得它之前生成该schema.sql?

P.S。 我不能将flyway用于生产环境。也许它可以用于测试吗?

UPD: 经过一些实验,我在test.yml中设置了这个:

Caused by: org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: missing table [application]

现在它加载上下文,执行一个只获取Oauth2令牌的测试,并且执行POST和GET请求的其他测试失败,因为它无法执行在测试方法之前放置其他数据的@sql注释。数据库似乎没有变化,没有任何表格。

2 个答案:

答案 0 :(得分:2)

您可以通过使用@TestPropertySource(properties = {"spring.flyway.enabled=true"})注释或使用自己的属性文件创建test Spring配置文件来启用flyway。后者看起来像:

@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles("test")
public MyTest {

使用src/test/resources/application-test.yml文件:

spring:
  flyway:
    enabled: true

flyway-core作为测试范围的依赖项。

请注意,Spring Boot中的Flyway属性已在Spring Boot 2.0中重命名。

答案 1 :(得分:1)

也许有人会觉得这很有用。 我设法通过使用带有故障安全插件的exec-maven-plugin来解决这个问题。 测试类设置保持不变,我只从Suite中删除了@BeforeClass注释。 这是POM:

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>${org.apache.maven.plugins.maven-surefire-plugin-version}</version>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>${org.apache.maven.plugins.maven-failsafe-plugin-version}</version>
                <executions>
                    <execution>
                        <id>integration-test-for-postgres</id>
                        <phase>integration-test</phase>
                        <goals>
                            <goal>integration-test</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>verify-for-postgres</id>
                        <phase>verify</phase>
                        <goals>
                            <goal>verify</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>${org.codehaus.mojo.exec-maven-plugin-version}</version>
                <executions>
                    <execution>
                        <id>build-test-environment</id>
                        <phase>generate-test-resources</phase>
                        <goals>
                            <goal>java</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <!--This class prepares the schema.sql file which is fed to Spring to init DB before tests.-->
                    <mainClass>...GenerateTestDBSchema</mainClass>
                    <arguments>
                        <argument>...</argument><!--the migration folder-->
                        <argument>...</argument><!--The path where to put schema sql-->
                    </arguments>
                </configuration>
            </plugin>
        </plugins>
    </build>

GenerateTestDBSchema类有main方法,并使用args数组接受查找迁移的路径以及schema.sql的放置位置。

public static void main(String[] args) {
        try {
            mergeMigrations(args[0], args[1]);
        } catch (IOException e) {
            LOG.error(e.getMessage());
        }
    }

mergeMigrations()方法很简单:只需从目录中获取所有文件,合并它们并写入输出路径。这样,Spring在启动上下文之前就拥有了schema.sql,它本身决定了迁移的运行位置。 感谢集成测试中的@ActiveProfiles(resolver = CustomActiveProfileResolver.class),spring解析配置文件并获取application- {profileName} .yml并自动设置数据库地址。