6

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?

4

6 回答 6

5

如何正确关闭 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。

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

于 2011-01-18T11:42:48.523 回答
4

如果您将 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)
  • 创建数据库结构(休眠)
  • 如果存在 import.sql 则执行(休眠)

每次测试后

  • 应用程序上下文被破坏(弹簧)
  • 数据库模式被删除(休眠)。

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

于 2012-05-11T11:36:27.587 回答
2

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

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/spring-test.xml")
public class MyTest {
}
于 2011-12-16T08:27:30.303 回答
1

只需执行以下操作:

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") 的范围。这将在每次测试之前获得数据源的新实例。

于 2011-01-17T22:23:46.040 回答
1

如果你使用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);
    }
}

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

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);
        }
}
于 2011-01-17T21:14:46.493 回答
0

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

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

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

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

      @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");
    
      }
    

奇迹般有效!

于 2016-05-06T19:55:34.090 回答