kol*_*len 23 unit-testing database-testing playframework playframework-2.0
我想创建单元测试,涵盖在Play框架2.1.0中使用关系数据库的代码.这有很多可能性,所有原因都有问题:
Play框架文档建议在H2内存数据库上运行单元测试,即使用于开发和生产的主数据库使用其他软件(即MySQL):
app = Helpers.fakeApplication(Helpers.inMemoryDatabase());
Run Code Online (Sandbox Code Playgroud)
我的应用程序不使用复杂的RDBMS功能,如存储过程,大多数数据库访问情况是ebean调用,因此它应该兼容MySQL和H2.
然而,在变阵创建表的语句中使用MySQL特定的功能,如指定ENGINE = InnoDB,DEFAULT CHARACTER SET = utf8等我担心我是否会删除这些专有部分CREATE TABLE,MySQL将使用一些默认设置,我无法控制和依赖的版本,所以测试和开发应用程序主MySQL配置必须修改.
任何人都使用这种方法(使evolutions与MySQL和H2兼容)?
其他想法如何处理:
create table(MySQL兼容模式不起作用,它仍然会抱怨default character set).我不知道怎么回事.H2内存数据库的唯一优势是它速度快,并且在与dev/production数据库相同的数据库驱动程序上进行测试可能会更好,因为它更接近真实环境.
如何在Play框架中完成?
尝试:
Map<String, String> settings = new HashMap<String, String>();
settings.put("db.default.url", "jdbc:mysql://localhost/sometestdatabase");
settings.put("db.default.jndiName", "DefaultDS");
app = Helpers.fakeApplication(settings);
Run Code Online (Sandbox Code Playgroud)
看起来像evolutions在这里工作,但在每次测试之前如何最好清理数据库?通过创建截断每个表的自定义代码?如果它会丢弃表格,那么演化会在下一次测试之前再次运行,还是每个play test命令应用一次?或者每次Helpers.fakeApplication()调用一次?
这里的最佳做法是什么?听说dbunit,有没有可能整合它没有太多的痛苦和怪癖?
首先,我建议您使用相同的RDBMS进行测试和生产,因为它可以避免一些难以发现的错误.
关于在每次测试之间清理数据库的需要,您可以使用Ebean DdlGenerator生成脚本来创建干净的数据库,使用JUnit的@Before注释来在每次测试之前自动执行这些脚本.
使用DdlGenerator可以这样做:
EbeanServer server = Ebean.getServer(serverName);
ServerConfig config = new ServerConfig();
DdlGenerator ddl = new DdlGenerator((SpiEbeanServer) server, new MySqlPlatform(), config);
Run Code Online (Sandbox Code Playgroud)
此代码可以放在一个基类中,您可以继承测试(或者在Runner可以与@RunWith注释一起使用的自定义内).
它还允许您轻松自动化FakeApplication创建,避免一些样板代码.
一些可能有用的链接:
在每次测试之前,我使用与主数据库和dbunit相同的数据库引擎进行清理.
public class SomeTest {
// ...
@Before
public void startApp() throws Exception {
// Set up connection to test database, different from main database. Config better should be used instead of hard-coding.
Map<String, String> settings = new HashMap<String, String>();
settings.put("db.default.url", "jdbc:mysql://localhost/somedatabase?characterEncoding=UTF-8&useOldAliasMetadataBehavior=true");
settings.put("db.default.user", "root");
settings.put("db.default.password", "root");
settings.put("db.default.jndiName", "DefaultDS"); // make connection available to dbunit through JNDI
app = Helpers.fakeApplication(settings);
Helpers.start(app);
databaseTester = new JndiDatabaseTester("DefaultDS");
IDataSet initialDataSet = new FlatXmlDataSetBuilder().build(play.Play.application()
.resourceAsStream("/resources/dataset.xml"));
databaseTester.setDataSet(initialDataSet);
databaseTester.onSetup();
}
@After
public void stopApp() throws Exception {
databaseTester.onTearDown();
Helpers.stop(app);
}
}
Run Code Online (Sandbox Code Playgroud)
我dataset.xml只是包含表名,告诉dbunit在每次测试之前清空这些表.它也可以包含固定装置.
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<name_of_my_first_table />
<name_of_my_second_table />
</dataset>
Run Code Online (Sandbox Code Playgroud)
使用此方法时,Evolutions会自动在测试数据库上运行,因此,如果从测试数据库中删除所有表,则会重新创建它们.
如果你只需要清理表就可以使用dbunit,你可以通过直接发出查询或使用ebean来清理它们DdlGenerator.但我也使用dbunit来比较数据.
我不使用Helpers.running,因为它需要Runnable和Runnable实现不能抛出异常 - 非常不方便测试.但是如果你看代码running(),它只是调用Helpers.start(),Helpers.stop()所以我直接在@Before和调用这些方法@After.
决定不使用H2进行运行测试:是的,运行速度更快,但它与MySQL之间存在太大差异.
| 归档时间: |
|
| 查看次数: |
12136 次 |
| 最近记录: |