玩!框架FakeApplication - 它实际上做了什么?

时间:2014-03-22 17:59:46

标签: java database unit-testing playframework

我一直在查看StackOverflow上的一些帖子,看看如何使用MYSQL数据库设置测试。

我只是想测试一些控制器方法,这些方法需要一个带有一些数据的测试数据库才能返回有意义的结果。我想使用一个真正的MYSQL数据库,因为我将在生产中使用它,我已经读过MYSQL和Play提供的InMemory数据库之间存在很多差异。

this onethis blog about testing Play! applications等帖子中,帖子显示了使用数据库参数初始化 FakeApplication 对象然后调用 Helper.start(fakeApp)的示例

Helper.start(FakeApplication app)docs给出了以下说明:

  

启动一个新的应用程序。

好的,好的。但是实际上通过调用start启动了哪些进程以及在测试中会给我带来什么?

Map<String, String> settings = new HashMap<String, String>();
settings.put("db.default.url", "jdbc:mysql://localhost/testdb");
settings.put("db.default.user", "root");
settings.put("db.default.password", "");

app = Helpers.fakeApplication(settings);
Helpers.start(app);

我希望上面的代码可以配置Ebean来使用我的测试数据库,但是当我尝试执行诸如 Ebean.save()之类的方法时,我得到一个错误,说没有默认数据库已在Ebean注册。为了注册,我需要填充 ServerConfig 对象并从 EbeanServerFactory 创建 EbeanServer 。在这种情况下,将设置映射传递给 FakeApplication 对象有什么意义吗?再一次,启动 FakeApplication 实际上做了什么?如何使用?

提前致谢。

1 个答案:

答案 0 :(得分:3)

我意识到你在一年多前问过这个问题,但我花了很长时间才弄明白这一点,所以希望这会在某些时候对某人有所帮助。

运行FakeApplication后,除了没有运行服务请求的网络服务器(netty)之外,你可以在说“激活器运行”后基本上做所有事情。但是,您可以将控制器测试为shown here,并调用访问数据库的方法。

除了this one之外,我实际上引用了你提到的那些帖子,其中讨论了一些必须设置的特殊魔术配置变量,你将在下面的例子中看到。

我创建了一个抽象的FakeApplicationTest类,我在单元/功能测试中进行了扩展。我首先使用我现有的application.conf文件,然后覆盖某些参数以针对不同的数据库进行测试。启动FakeApplication后,我会阅读所有演变并创建一个新的数据库来运行我的测试。

public abstract class FakeApplicationTest {

    protected static FakeApplication app;

    /**
     * Create a new FakeApplication using all our custom config vars that test against diff DB's
     *
     * @return
     */
    public static FakeApplication createFakeApp() {
        // grab the main application.conf file that is used to start up the Play application
        Config config = ConfigFactory.parseFile(new File("conf/application.conf"));

        // resolve all variables within this config file with other variables within itself
        config = ConfigFactory.load(config);

        // create a Configuration object out of this and then turn it into a Map to be modified
        Configuration configuration = new Configuration(config);
        Map<String, Object> fakeApplicationConf = Maps.newHashMap(configuration.asMap());

        // do some crazy stuff here because Play wants us to for config voodoo, see:
        // http://www.stupidjavatricks.com/2013/05/changing-play-2-db-configuration-at-runtime-beware-of-dragons/
        Configuration akka = configuration.getConfig("akka.actor.serialization-bindings");
        addValue(fakeApplicationConf, "akka.actor.serialization-bindings", null);
        addValue(fakeApplicationConf, "akka.actor.serialization-bindings.\"[B\"", akka.getString("\"[\"B"));
        addValue(fakeApplicationConf, "akka.actor.serialization-bindings.\"java.io.Serializable\"", akka.getString("\"java.io.Serializable\""));

        // point at a different test database
        addValue(fakeApplicationConf, "db.default.url", "jdbc:mysql://127.0.0.1/testdb");
        addValue(fakeApplicationConf, "db.default.user", "someuser");
        addValue(fakeApplicationConf, "db.default.password", "hunter2");

        // disable evolutions and just create the DB manually
        addValue(fakeApplicationConf, "evolutionplugin", "disabled");

        return Helpers.fakeApplication(fakeApplicationConf);
    }

    @BeforeClass
    public static void setUp() throws Exception {
        app = createFakeApp();

        // fire up the Fake Application!
        Helpers.start(app);

        // after we start up the application, create a database
        createCleanDb();
    }

    @AfterClass
    public static void tearDown() throws Exception {
        Helpers.stop(app);
    }

    ...
}

有很多东西可以读出演变并按顺序应用它们,但我现在已经把它留了出来。