JUnit +德比战Spring:每次测试后删除内存数据库

发布于 2024-10-12 11:03:03 字数 267 浏览 2 评论 0原文

在我的单元测试中,我自动连接了一些数据源,它们使用 URL

jdbc:derby:memory:mydb;create=true

来创建内存数据库。

要删除内存中的 Derby 数据库,您必须连接:

jdbc:derby:memory:mydb;drop=true

我希望在每次测试后都发生这种情况,并从一个新的数据库开始。我怎样才能使用 Spring 来做到这一点?

In my unit tests I autowired some DataSources, which use URLs like

jdbc:derby:memory:mydb;create=true

to create an in-memory DBs.

To drop an in-memory Derby db you have to connect with:

jdbc:derby:memory:mydb;drop=true

I would like this to happen after every test and start with a fresh db. How can I do this using Spring?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

我不咬妳我踢妳 2024-10-19 11:03:03

如何正确关闭 Derby 内存数据库

给了我一个解决方案提示:

    mydb.drop.url = jdbc:derby:memory:mydb;drop=true

    ...

    <bean id="mydbDropUrl" class="java.lang.String">
    <constructor-arg value="${mydb.drop.url}" />
</bean>

    ...

    @Resource
private String mydbDropUrl;        

    @After
public void tearDown() {
    try {
        DriverManager.getConnection(mydbDropUrl);
    } catch (SQLException e) {
        // ignore
    }
}

缺点是使用 String 构造函数,该构造函数接受 String(围绕不可变 String 对象的不可变 String 对象)。我读到 Spring 3 中有一个 @Value 注释,这可能会有所帮助,但我正在使用 Spring 2.5。

如果您有更好的解决方案,请告诉我。

How to shutdown Derby in-memory database Properly

gave me a hint to a solution:

    mydb.drop.url = jdbc:derby:memory:mydb;drop=true

    ...

    <bean id="mydbDropUrl" class="java.lang.String">
    <constructor-arg value="${mydb.drop.url}" />
</bean>

    ...

    @Resource
private String mydbDropUrl;        

    @After
public void tearDown() {
    try {
        DriverManager.getConnection(mydbDropUrl);
    } catch (SQLException e) {
        // ignore
    }
}

A downside is the use of the String constructor which accepts a String (an immutable String object around an immutable String object). I read that there is a @Value annotation in Spring 3, which might help here, but I'm using Spring 2.5.

Please let me know if you have a nicer solution.

记忆里有你的影子 2024-10-19 11:03:03

如果您将 Spring 与 Hibernate 一起使用,则有一种与数据库无关的方法可以做到这一点。

确保在每个测试方法之前/之后创建/销毁应用程序上下文:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath*:application-context-test.xml"})
@TestExecutionListeners({DirtiesContextTestExecutionListener.class, 
    DependencyInjectionTestExecutionListener.class})
@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
public abstract class AbstractTest {

}

指示 Hibernate 在启动时自动创建模式并在关闭时删除模式:

hibernate.hbm2ddl.auto = create-drop

现在,在每个测试之前

  • 创建应用程序上下文并注入所需的 spring bean (spring)
  • 创建数据库结构 (hibernate)
  • 如果存在则执行 import.sql (hibernate)

,并且在每次测试后

  • 销毁应用程序上下文 (spring)
  • 删除数据库模式 (hibernate)。

如果您使用事务,您可能需要添加 TransactionalTestExecutionListener

There is a database-agnostic way to do this if you are using Spring together with Hibernate.

Make sure the application context will be created / destroyed before / after every test method:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath*:application-context-test.xml"})
@TestExecutionListeners({DirtiesContextTestExecutionListener.class, 
    DependencyInjectionTestExecutionListener.class})
@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
public abstract class AbstractTest {

}

Instruct Hibernate to auto create the schema on startup and to drop the schema on shutdown:

hibernate.hbm2ddl.auto = create-drop

Now before every test

  • the application context is created and the required spring beans are injected (spring)
  • the database structures are created (hibernate)
  • the import.sql is executed if present (hibernate)

and after every test

  • the application context is destroyed (spring)
  • the database schema is dropped (hibernate).

If you are using transactions, you may want to add the TransactionalTestExecutionListener.

烟─花易冷 2024-10-19 11:03:03

spring test 3之后,可以使用注解注入配置:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/spring-test.xml")
public class MyTest {
}

After spring test 3, you can use annotations to inject configurations:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/spring-test.xml")
public class MyTest {
}
青瓷清茶倾城歌 2024-10-19 11:03:03

只需执行以下操作:

public class DatabaseTest implements ApplicationContextAware {
    private ApplicationContext context;
    private DataSource source;

    public void setApplicationContext(ApplicationContext applicationContext) {
        this.context = applicationContext;
    }

    @Before
    public void before() {
        source = (DataSource) dataSource.getBean("dataSource", DataSource.class);
    }

    @After
    public void after() {
        source = null;
    }
}

使您的 bean 具有原型范围 (scope="prototype")。这将在每次测试之前获取数据源的新实例。

Just do something like:

public class DatabaseTest implements ApplicationContextAware {
    private ApplicationContext context;
    private DataSource source;

    public void setApplicationContext(ApplicationContext applicationContext) {
        this.context = applicationContext;
    }

    @Before
    public void before() {
        source = (DataSource) dataSource.getBean("dataSource", DataSource.class);
    }

    @After
    public void after() {
        source = null;
    }
}

Make your bean have a scope of prototype (scope="prototype"). This will get a new instance of the data source before every test.

薔薇婲 2024-10-19 11:03:03

如果您使用 spring-test.jar 库,您可以执行以下操作:

public class MyDataSourceSpringTest extends
AbstractTransactionalDataSourceSpringContextTests {

    @Override
    protected String[] getConfigLocations() {
        return new String[]{"classpath:test-context.xml"};
    }

    @Override
    protected void onSetUpInTransaction() throws Exception {
        super.deleteFromTables(new String[]{"myTable"});
        super.executeSqlScript("file:db/load_data.sql", true);
    }
}

基于最新评论的更新版本,在每次测试之前删除数据库并重新创建表:

public class MyDataSourceSpringTest extends
    AbstractTransactionalDataSourceSpringContextTests {

        @Override
        protected String[] getConfigLocations() {
            return new String[]{"classpath:test-context.xml"};
        }

        @Override
        protected void onSetUpInTransaction() throws Exception {
            super.executeSqlScript("file:db/recreate_tables.sql", true);
        }
}

If you use the spring-test.jar library, you can do something like this:

public class MyDataSourceSpringTest extends
AbstractTransactionalDataSourceSpringContextTests {

    @Override
    protected String[] getConfigLocations() {
        return new String[]{"classpath:test-context.xml"};
    }

    @Override
    protected void onSetUpInTransaction() throws Exception {
        super.deleteFromTables(new String[]{"myTable"});
        super.executeSqlScript("file:db/load_data.sql", true);
    }
}

And an updated version based on latest comment, that drops db and recreates tables before every test:

public class MyDataSourceSpringTest extends
    AbstractTransactionalDataSourceSpringContextTests {

        @Override
        protected String[] getConfigLocations() {
            return new String[]{"classpath:test-context.xml"};
        }

        @Override
        protected void onSetUpInTransaction() throws Exception {
            super.executeSqlScript("file:db/recreate_tables.sql", true);
        }
}
入怼 2024-10-19 11:03:03

这就是我们在每次测试开始时所做的事情。

  1. 删除所有先前的对象。

  2. 创建create_table.sql中提到的所有表

  3. 根据要测试的内容将值插入到创建的表中。

    <前><代码>@之前
    公共无效initialInMemoryDatabase()抛出IOException,FileNotFoundException {

    inMemoryDe​​rbyDatabase.dropAllObjects();
    inMemoryDe​​rbyDatabase.executeSqlFile("/create_table_policy_version_manager.sql");
    inMemoryDe​​rbyDatabase.executeSqlFile("/insert_table_policy_version_manager.sql");

    }

效果就像一个魅力!

This is what we do at the start of every test.

  1. Drop all Previous Objects.

  2. Create all tables mentioned in the create_table.sql

  3. Insert values onto the created tables based on what you want to test.

      @Before
      public void initialInMemoryDatabase() throws IOException, FileNotFoundException {
    
      inMemoryDerbyDatabase.dropAllObjects();
      inMemoryDerbyDatabase.executeSqlFile("/create_table_policy_version_manager.sql");
      inMemoryDerbyDatabase.executeSqlFile("/insert_table_policy_version_manager.sql");
    
      }
    

Works like a charm!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文