unit-testing - 如何在 Play 框架中针对非内存数据库(如 MySQL)创建单元测试,并重置为已知状态?

标签 unit-testing playframework playframework-2.0 database-testing

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

在内存 H2 数据库上进行测试

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

app = Helpers.fakeApplication(Helpers.inMemoryDatabase());

我的应用程序不使用存储过程等复杂的 RDBMS 功能,并且大多数数据库访问案例都是 ebean 调用,因此它应该与 MySQL 和 H2 兼容。

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

有人使用过这种方法(使进化与 MySQL 和 H2 兼容)吗?

如何处理它的其他想法:
  • MySQL 和 H2 的单独演进(不是一个好主意)
  • 使 H2 忽略 create table 中的其他 MySQL 内容的某种方法(MySQL 兼容模式不起作用,即使在 default character set 上它仍然会提示)。我不知道怎么做。

  • 在与主数据库相同的数据库驱动程序上进行测试

    H2 内存数据库的唯一优势是速度快,并且在相同的数据库驱动程序上进行测试可能比开发/生产数据库更好,因为它更接近真实环境。

    如何在 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);
    

    看起来进化在这里起作用,但是在每次测试之前最好如何清理数据库?通过创建截断每个表的自定义代码?如果它会删除表,那么进化将在下一次测试之前再次运行,或者每个 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);
    

    这段代码可以放在一个基类中,你可以继承你的测试(或者在一个自定义的Runner中,你可以使用@RunWith注解)。

    它还可以让您轻松自动化 FakeApplication创建,避免一些样板代码。

    一些可能有用的链接:
  • http://blog.matthieuguillermin.fr/2012/03/unit-testing-tricks-for-play-2-0-and-ebean/
  • https://gist.github.com/nboire/2819920
  • 关于unit-testing - 如何在 Play 框架中针对非内存数据库(如 MySQL)创建单元测试,并重置为已知状态?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14750375/

    相关文章:

    c# - 断言后如何获取异常对象?

    c# - 更改私有(private)字段状态的方法的单元测试

    c# - MSTest.exe 给出程序集或模块未找到警告

    java - 在 PlayFramework 中自定义 CRUD list.html

    scala - 如何使用 Scala 在路由上绑定(bind)枚举?

    scala - Play 框架模板没有 Html 类型

    unit-testing - 在 JUnit 的方法内模拟对象

    scala - Groovy Grails 或 Scala Play

    unit-testing - 如何在 Play 2.0 框架中为路由编写隔离单元测试?

    scala - Squeryl:显式运行查询