java JUnit + Derby + Spring:每次测试后删除内存数据库
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4717865/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JUnit + Derby + Spring: drop in-memory db after every test
提问by Puce
In my unit tests I autowired some DataSources, which use URLs like
在我的单元测试中,我自动装配了一些 DataSources,它们使用 URLs
jdbc:derby:memory:mydb;create=true
to create an in-memory DBs.
创建内存数据库。
To drop an in-memory Derby db you have to connect with:
要删除内存中的 Derby 数据库,您必须连接:
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?
我希望每次测试后都会发生这种情况,并从一个新的数据库开始。如何使用 Spring 执行此操作?
采纳答案by Puce
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.
一个缺点是使用接受 String 的 String 构造函数(围绕不可变 String 对象的不可变 String 对象)。我读到 Spring 3 中有一个 @Value 注释,这可能会有所帮助,但我使用的是 Spring 2.5。
Please let me know if you have a nicer solution.
如果您有更好的解决方案,请告诉我。
回答by tekbe
There is a database-agnostic way to do this if you are using Spring together with Hibernate.
如果您将 Spring 与 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 在启动时自动创建模式并在关闭时删除模式:
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)
- 创建应用程序上下文并注入所需的spring bean(spring)
- 创建数据库结构(休眠)
- 如果存在,则执行 import.sql(休眠)
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
.
如果您正在使用事务,您可能需要添加TransactionalTestExecutionListener
.
回答by Jay
After spring test 3, you can use annotations to inject configurations:
spring test 3后,可以使用注解注入配置:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/spring-test.xml")
public class MyTest {
}
回答by Maria Ioannidou
If you use the spring-test.jarlibrary, you can do something like this:
如果使用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);
}
}
And an updated version based on latest comment, that drops db and recreates tables before every test:
以及基于最新评论的更新版本,在每次测试之前删除 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);
}
}
回答by hisdrewness
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.
使您的 bean 具有原型 ( scope="prototype"
)的范围。这将在每次测试之前获得数据源的新实例。
回答by Gautham Honnavara
This is what we do at the start of every test.
这就是我们在每次测试开始时所做的。
Drop all Previous Objects.
Create all tables mentioned in the create_table.sql
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"); }
删除所有以前的对象。
创建 create_table.sql 中提到的所有表
根据您要测试的内容将值插入到创建的表中。
@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!
奇迹般有效!