我最近将Ember应用程序从2.18升级到3.13,运行顺利。今天,我尝试首次添加验收测试(在此之前仅进行了集成/单元测试),但是测试在第一行失败:
import { module, test } from "qunit";
import { visit, currentURL } from "@ember/test-helpers";
import { setupApplicationTest } from "ember-qunit";
module("Acceptance | some route", function(hooks) {
setupApplicationTest(hooks);
test("visiting /some-route", async function(assert) {
await visit("/some-route"); // <----- error thrown here
assert.equal(currentURL(), "/some-route");
});
});
我看到几个错误(按此顺序):
Source:
TypeError: Cannot read property 'lookup' of undefined
at Object.initialize (http://localhost:4200/assets/my-app.js:10312:28)
at http://localhost:4200/assets/vendor.js:61627:21
at Vertices.each (http://localhost:4200/assets/vendor.js:80243:9)
at Vertices.walk (http://localhost:4200/assets/vendor.js:80157:12)
at DAG.each (http://localhost:4200/assets/vendor.js:80087:22)
at DAG.topsort (http://localhost:4200/assets/vendor.js:80095:12)
at Class._runInitializer (http://localhost:4200/assets/vendor.js:61653:13)
at Class.runInitializers (http://localhost:4200/assets/vendor.js:61625:12)
at Class._bootSync (http://localhost:4200/assets/vendor.js:59923:14)
at Class.boot (http://localhost:4200/assets/vendor.js:59890:14)
Source:
Error: Cannot call `visit` without having first called `setupApplicationContext`.
at visit (http://localhost:4200/assets/test-support.js:44177:13)
at Object._callee$ (http://localhost:4200/assets/tests.js:23:47)
at tryCatch (http://localhost:4200/assets/vendor.js:12365:40)
at Generator.invoke [as _invoke] (http://localhost:4200/assets/vendor.js:12591:22)
at Generator.prototype.<computed> [as next] (http://localhost:4200/assets/vendor.js:12417:21)
at asyncGeneratorStep (http://localhost:4200/assets/tests.js:6:105)
at _next (http://localhost:4200/assets/tests.js:8:196)
at http://localhost:4200/assets/tests.js:8:366
at new Promise (<anonymous>)
at Object.<anonymous> (http://localhost:4200/assets/tests.js:8:99)
经过一番挖掘后,似乎是错误地设置了测试上下文。它只是一个空对象:
因此,isApplicationTestContext(context)
返回false,并且引发第二个错误。我猜是因为应用程序有一些执行查询的初始化程序而引发了第一个错误。
为了添加此验收测试,我还将test-helper.js
文件更新为以下内容:
import Application from "../app";
import config from "../config/environment";
import { setApplication } from "@ember/test-helpers";
import { start } from "ember-qunit";
setApplication(Application.create(config.APP));
start();
使用上述文件,all测试失败,因此看来setApplication
导致测试上下文设置不正确?旧的test-helper.js
文件如下所示:
import resolver from "./helpers/resolver";
import { setResolver } from "@ember/test-helpers";
import { start } from "ember-cli-qunit";
setResolver(resolver);
start();
我尝试重新添加setResolver
调用,但没有什么区别。还有其他人使用新的ember-qunit语法遇到这些问题吗,或者可能会看到我做错了什么?另外,我在autoboot = false;
文件中设置了environment.js
,这没有什么区别。该测试套件还具有一个或两个测试,仍然使用较旧的ember-qunit语法编写。任何帮助,将不胜感激!
首先是一些背景故事:
我们的应用程序使用第三方库进行度量,并使用第三方库进行特征标记。每个库都有其自己的服务,但是我们需要在功能标记服务可以初始化之前初始化指标服务,因为我们要链接分析用户数据以获得每个用户正确的功能标记。在整个应用程序中都完成了功能标志检查,因此在何时进行功能标志检查与何时在网页上的脚本标签中加载分析文件之间出现了竞争状况。
现在解决:
出现此错误的原因:
Source:
TypeError: Cannot read property 'lookup' of undefined
at Object.initialize (http://localhost:4200/assets/my-app.js:10312:28)
at http://localhost:4200/assets/vendor.js:61627:21
at Vertices.each (http://localhost:4200/assets/vendor.js:80243:9)
at Vertices.walk (http://localhost:4200/assets/vendor.js:80157:12)
at DAG.each (http://localhost:4200/assets/vendor.js:80087:22)
at DAG.topsort (http://localhost:4200/assets/vendor.js:80095:12)
at Class._runInitializer (http://localhost:4200/assets/vendor.js:61653:13)
at Class.runInitializers (http://localhost:4200/assets/vendor.js:61625:12)
at Class._bootSync (http://localhost:4200/assets/vendor.js:59923:14)
at Class.boot (http://localhost:4200/assets/vendor.js:59890:14)
是因为该应用程序具有一个应用程序初始化程序,该初始化程序正在利用私有Ember API从容器中执行查找。初始化程序正在执行查找以隐式初始化指标服务,然后再获取分析数据,然后初始化功能标志服务。
export function initialize(application) {
const container = application.__container__; // <-- undefined
const lookup = container.lookup.bind(application.__container__); // <-- error!
...
}
奇怪的是,以上代码在development
和production
环境中有效。此更改似乎是由于内部Ember API(特别是与容器相关)的弃用/重新布置而导致的。 See this page for more information。
为了访问应用程序初始化程序中的容器,必须从应用程序实例(即实例初始化程序)完成操作。这可能是一个可以接受的解决方案,但我不确定100%是否可以推迟应用程序实例初始化程序的应用程序就绪状态。
有关应用程序实例初始化程序的更多阅读,see here。
相反,代码已移至应用程序路由的beforeModel()
挂钩。我还为指标服务添加了实例初始化程序,从而缩短了应用程序加载时间。
将初始化程序代码移至应用程序路径后,现在已成功构建了应用程序,并且验收测试就像一个超级按钮。 :)