【问题标题】:Run migrations programmatically in Dropwizard在 Dropwizard 中以编程方式运行迁移
【发布时间】:2015-08-21 00:19:26
【问题描述】:

我有 dropwizard-application (0.7.0),我想为其运行集成测试。

我已经使用 DropwizardAppRule 设置了一个集成测试,如下所示:

@ClassRule
public static final DropwizardAppRule<MyAppConfiguration> RULE =
        new DropwizardAppRule<MyAppConfiguration>(
                MyApplication.class, Resources.getResource("testconfiguration.yml").getPath());

当我尝试使用它运行以下测试时,它不起作用,因为我还没有运行我的迁移。运行迁移的最佳方式是什么?

测试:

@Test
public void fooTest() {
    Client client = new Client();
    String root = String.format("http://localhost:%d/", RULE.getLocalPort());
    URI uri = UriBuilder.fromUri(root).path("/users").build();
    client.resource(uri).accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).post(User.class, new LoginUserDTO("email@email.com", "password"));
}

配置:

 public class MyAppConfiguration extends Configuration {
@Valid
@NotNull
private DataSourceFactory database = new DataSourceFactory();

@JsonProperty("database")
public DataSourceFactory getDataSourceFactory() {
    return database;
}

@JsonProperty("database")
public void setDataSourceFactory(DataSourceFactory dataSourceFactory) {
    this.database = dataSourceFactory;
}

}

【问题讨论】:

    标签: java liquibase dropwizard


    【解决方案1】:

    感谢 Kimble 和 andersem 让我走上了正轨。这是我在@BeforeClass 方法中提出的:

    // Create the test database with the LiquiBase migrations.
    @BeforeClass
    public static void up() throws Exception
    {
        ManagedDataSource ds = RULE.getConfiguration().getMainDataSource().build(
            RULE.getEnvironment().metrics(), "migrations");
        try (Connection connection = ds.getConnection())
        {
            Liquibase migrator = new Liquibase("migrations.xml", new ClassLoaderResourceAccessor(), new JdbcConnection(connection));
            migrator.update("");
        }
    }
    

    【讨论】:

      【解决方案2】:

      我在尝试将数据库迁移作为测试用例的一部分时遇到了一些并发问题,最终将其烘焙到应用程序本身(受配置选项保护)。

      private void migrate(MyAppConfiguration configuration, Environment environment) {
          if (configuration.isMigrateSchemaOnStartup()) {
              log.info("Running schema migration");
              ManagedDataSource dataSource = createMigrationDataSource(configuration, environment);
      
              try (Connection connection = dataSource.getConnection()) {
                  JdbcConnection conn = new JdbcConnection(connection);
      
                  Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(conn);
                  Liquibase liquibase = new Liquibase("migrations.xml", new ClassLoaderResourceAccessor(), database);
                  liquibase.update("");
      
                  log.info("Migration completed!");
              }
              catch (Exception ex) {
                  throw new IllegalStateException("Unable to migrate database", ex);
              }
              finally {
                  try {
                      dataSource.stop();
                  }
                  catch (Exception ex) {
                      log.error("Unable to stop data source used to execute schema migration", ex);
                  }
              }
          }
          else {
              log.info("Skipping schema migration");
          }
      }
      
      private ManagedDataSource createMigrationDataSource(MyAppConfiguration configuration, Environment environment) {
          DataSourceFactory dataSourceFactory = configuration.getDataSourceFactory();
      
          try {
              return dataSourceFactory.build(environment.metrics(), "migration-ds");
          }
          catch (ClassNotFoundException ex) {
              throw new IllegalStateException("Unable to initialize data source for schema migration", ex);
          }
      }
      

      【讨论】:

        【解决方案3】:

        另一种不依赖于直接导入 Liquibase 类的方法是使用 RULE 以与从命令行相同的方式运行 db migrate 命令:

        @Before
        public void migrateDatabase() throws Exception {
            RULE.getApplication().run("db", "migrate", ResourceHelpers.resourceFilePath("testconfiguration.yml"));
        }
        

        此方法也适用于您可能希望在开始测试之前运行的任何其他捆绑包中的任何其他命令。

        一个小问题:使用扩展 Dropwizards ConfiguredCommand 的任何命令(所有 dropwizard-migrations 都这样做)执行此操作将在命令完成时不必要地禁用 logback。 要恢复它,您可以调用:

                RULE.getConfiguration().getLoggingFactory().configure(RULE.getEnvironment().metrics(),
                    RULE.getApplication().getName());
        

        【讨论】:

          【解决方案4】:

          我是使用 Liquibase 的 API 这样做的:

          private void migrate(){
              DataSourceFactory dataSourceFactory = RULE.getConfiguration().dataSourceFactory;
              Properties info = new Properties();
              info.setProperty("user", dataSourceFactory.getUser());
              info.setProperty("password", dataSourceFactory.getPassword());
              org.h2.jdbc.JdbcConnection h2Conn = new org.h2.jdbc.JdbcConnection(dataSourceFactory.getUrl(), info);
              JdbcConnection conn = new JdbcConnection(h2Conn);
              Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(conn);
              Liquibase liquibase = new Liquibase("migrations.xml", new ClassLoaderResourceAccessor(), database);
              String ctx = null;
              liquibase.update(ctx);
          }
          

          然后我把它放在课前:

          @BeforeClass
          public void setup(){
              migrate();
          }
          

          这可能不是最终的解决方案,它在很大程度上取决于您使用的数据库,但它确实有效。

          【讨论】:

            【解决方案5】:

            为了实现同样的目标,我所做的是在 maven 中运行迁移。

            将此添加到 您的 pom.xml 部分中的部分:

            <plugin>
              <groupId>org.liquibase</groupId>
              <artifactId>liquibase-maven-plugin</artifactId>
              <version>3.0.5</version>
              <executions>
                  <execution>
                      <phase>process-test-resources</phase>  
                      <configuration>
                        <changeLogFile>PATH TO YOUR MIGRATIONS FILE</changeLogFile>
                        <driver>org.h2.Driver</driver>
                        <url>JDBC URL LIKE IN YOUR APP.YML</url>
                        <username>USERNAME</username>
                        <password>PASSWORD</password>
                        <dropFirst>false</dropFirst>
                        <promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
                        <logging>info</logging>
                      </configuration>
                      <goals>
                        <goal>dropAll</goal>
                        <goal>update</goal>
                      </goals>
                  </execution>
              </executions>               
            </plugin>
            

            这将适用于命令行中的 maven。使用此设置,maven 将使用 liquibase dropAll 删除所有数据库对象,然后运行迁移,因此每次测试您都有一个干净的新数据库。

            在使用它时,我遇到了 eclipse 的问题,它抱怨生命周期映射不适用于插件的执行标签。在这种情况下,您还需要将以下内容添加到构建部分,以便 eclipse 可以正确映射生命周期:

            <pluginManagement>
              <plugins>
                <plugin>
                  <groupId>org.eclipse.m2e</groupId>
                  <artifactId>lifecycle-mapping</artifactId>
                  <version>1.0.0</version>
                  <configuration>
                    <lifecycleMappingMetadata>
                    <pluginExecutions>
                      <pluginExecution>
                        <pluginExecutionFilter>
                          <groupId>org.liquibase</groupId>
                          <artifactId>liquibase-maven-plugin</artifactId>
                          <versionRange>[1.0,)</versionRange>
                          <goals>
                            <goal>dropAll</goal>
                            <goal>update</goal>
                          </goals>
                        </pluginExecutionFilter>
                        <action>
                          <execute />
                        </action>
                      </pluginExecution>
                    </pluginExecutions>
                    </lifecycleMappingMetadata>
                  </configuration>
                </plugin>
              </plugins>
              </pluginManagement>  
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2017-10-10
              • 2015-09-16
              • 2016-07-04
              • 2016-03-11
              • 1970-01-01
              相关资源
              最近更新 更多