Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/389.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unit testing 如何针对非内存数据库(如MySQL in Play framework)创建单元测试,并重置为已知状态?_Unit Testing_Playframework_Playframework 2.0_Database Testing - Fatal编程技术网

Unit testing 如何针对非内存数据库(如MySQL in Play framework)创建单元测试,并重置为已知状态?

Unit testing 如何针对非内存数据库(如MySQL in Play framework)创建单元测试,并重置为已知状态?,unit-testing,playframework,playframework-2.0,database-testing,Unit Testing,Playframework,Playframework 2.0,Database Testing,我想创建单元测试,涵盖在Play framework 2.1.0中使用关系数据库的代码。这有很多可能,并且都会导致问题: 内存H2数据库的测试 Play framework文档建议在H2内存数据库上运行单元测试,即使用于开发和生产的主数据库使用其他软件(如MySQL): app=Helpers.fakeApplication(Helpers.inMemoryDatabase()); 我的应用程序不使用复杂的RDBMS特性,例如存储过程,并且大多数数据库访问案例都是ebean调用,因此它应该与M

我想创建单元测试,涵盖在Play framework 2.1.0中使用关系数据库的代码。这有很多可能,并且都会导致问题:

内存H2数据库的测试 Play framework文档建议在H2内存数据库上运行单元测试,即使用于开发和生产的主数据库使用其他软件(如MySQL):

app=Helpers.fakeApplication(Helpers.inMemoryDatabase());
我的应用程序不使用复杂的RDBMS特性,例如存储过程,并且大多数数据库访问案例都是ebean调用,因此它应该与MySQL和H2兼容

然而,evolutions中的表创建语句使用MySQL特有的功能,例如指定
ENGINE=InnoDB
DEFAULT CHARACTER SET=utf8
,等等。我担心如果我删除
CREATE table
的这些专有部分,MySQL将使用一些我无法控制且取决于版本的默认设置,所以,为了测试和开发应用程序,必须修改主MySQL配置

有人使用过这种方法(使evolutions与MySQL和H2兼容)

如何处理它的其他想法:

  • MySQL和H2的独立演进(不是一个好主意)
  • create table
    (MySQL兼容模式不起作用,即使在
    默认字符集上,它仍然会抱怨)中,H2会忽略额外的MySQL内容。我不知道怎么做
在与主数据库相同的数据库驱动程序上进行测试 H2内存数据库的唯一优点是速度快,在同一个数据库驱动程序上进行测试可能比在开发/生产数据库上进行测试更好,因为它更接近真实环境

如何在Play框架中正确完成

尝试:

Map settings=newhashmap();
settings.put(“db.default.url”,“jdbc:mysql://localhost/sometestdatabase");
settings.put(“db.default.jndiName”、“DefaultDS”);
app=Helpers.fakeApplication(设置);
看起来进化在这里起作用,但在每次测试之前如何最好地清理数据库呢?通过创建截断每个表的自定义代码?如果它将删除表,那么在下一次测试之前,演进是否会再次运行,或者每个
play test
命令应用它们一次?或者每次调用
Helpers.fakeApplication()
一次


这里的最佳实践是什么?听说过,有没有可能不费吹灰之力就集成它?

首先,我建议您在测试和生产中使用相同的RDBMS,因为它可以避免一些难以发现的bug

关于在每次测试之间清理数据库的需要,您可以使用Ebean
DdlGenerator
生成脚本以创建干净的数据库,并使用JUnit的
@Before
注释在每次测试之前自动执行这些脚本

使用
DdlGenerator
可以这样做:

    EbeanServer server = Ebean.getServer(serverName);
    ServerConfig config = new ServerConfig();
    DdlGenerator ddl = new DdlGenerator((SpiEbeanServer) server, new MySqlPlatform(), config);
这段代码可以放在一个基类中,您可以让它继承您的测试(或者放在一个自定义的
Runner
中,您可以使用
@RunWith
注释)

它还允许您轻松地自动化
FakeApplication
创建,避免一些样板代码

一些可能有用的链接:


我使用与主数据库相同的数据库引擎,并在每次测试之前进行清理

公共类测试{
// ...
@以前
public void startApp()引发异常{
//设置与测试数据库的连接,与主数据库不同。应使用更好的配置,而不是硬编码。
映射设置=新建HashMap();
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”);//通过JNDI使连接对dbunit可用
app=Helpers.fakeApplication(设置);
Helpers.start(应用程序);
databaseTester=新的JndiDatabaseTester(“DefaultDS”);
IDataSet initialDataSet=new FlatXmlDataSetBuilder().build(play.play.application())
.resourceAsStream(“/resources/dataset.xml”);
databaseTester.setDataSet(initialDataSet);
databaseTester.onSetup();
}
@之后
public void stopApp()引发异常{
databaseTester.onTearDown();
Helpers.stop(应用程序);
}
}
My
dataset.xml
只包含表名,用于在每次测试之前告诉dbunit清空这些表。它还可以包含装置


当使用这种方法时,演进会在测试数据库上自动运行,所以若您从测试数据库中删除所有表,它们将被重新创建

如果您只需要清理表,那么使用dbunit就太过分了。您可以通过直接发出查询或使用ebean
DdlGenerator
来清理表。但我也使用dbunit来比较数据

我不使用
Helpers.running
,因为它需要
Runnable
并且
Runnable
实现不能抛出异常-这对测试非常不方便。但是如果您查看
running()
的代码,它只调用
Helpers.start()
Helpers.stop()
,所以我直接在
@Before
@Before
中调用这些方法

决定不使用H2来运行测试:是的,它运行得更快,但它和MySQL之间有太多的区别

有人使用过这种方法(使evolutions与MySQL和H2兼容)


我已经找到了MySQL特定功能的答案:

当我为我的postgres数据库编写测试时,我只是创建了一个HashMap连接到数据库,然后编写了测试查询以确保记录量正确
    @Test
public void testDataBase() {
    final HashMap<String,String> postgres = new HashMap<String, String>();
    postgres.put("db.default.driver","org.postgresql.Driver");
    postgres.put("db.default.url","jdbc:postgresql://localhost/myDataBase");
    postgres.put("db.default.user", "postgres");
    postgres.put("db.default.password", "password");

    running(fakeApplication(postgres), new Runnable() {

        @Override
        public void run() {

            //Insert Assertions Here
        }
    });
}