setApplication нарушает тестовый контекст ember-qunit
Недавно я обновил приложение 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();
С указанным выше файлом все тесты не работают, поэтому кажется, что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. Любая помощь будет оценена по достоинству!
1 ответ
Для начала немного предыстории:
Наше приложение использует стороннюю библиотеку для показателей и другую стороннюю библиотеку для флагов функций. Каждая библиотека имеет свою собственную службу, но нам нужно, чтобы служба метрик была инициализирована до того, как можно будет инициализировать службу флагов функций, потому что мы хотим связать аналитические данные пользователя, чтобы получить правильные флаги функций для каждого пользователя. Проверка флага функции выполняется во всем приложении, поэтому между моментом, когда должна произойти проверка флага функции, и загрузкой файла аналитики в тег скрипта на веб-странице возникла гонка.
Теперь решение:
Причина появления этой ошибки:
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)
потому, что в приложении есть инициализатор приложения, который использовал частные API Ember для выполнения поиска из контейнера. Инициализатор выполнял поиск для неявной инициализации службы метрик перед извлечением аналитических данных и последующей инициализацией службы флага функции.
export function initialize(application) {
const container = application.__container__; // <-- undefined
const lookup = container.lookup.bind(application.__container__); // <-- error!
...
}
Что странно, приведенный выше код работает в development
а также production
среды. Это изменение, похоже, является результатом устаревания / перестановки внутренних API-интерфейсов Ember, особенно связанных с контейнером. См. Эту страницу для получения дополнительной информации.
Чтобы получить доступ к контейнеру в инициализаторе приложения, это должно быть сделано из экземпляра приложения (т. Е. Инициализатора экземпляра). Это могло быть приемлемым решением, но я не был на 100% уверен, можно ли отложить готовность приложения из инициализатора экземпляра приложения.
Дополнительную информацию об инициализаторах экземпляров приложения см. Здесь.
Вместо этого код был перемещен в маршрут приложения beforeModel()
крючок. Я также добавил инициализатор экземпляра для службы метрик, что привело к более быстрой загрузке приложения.
После перемещения кода инициализатора в маршрут приложения приложение теперь успешно создается, и приемочные тесты работают как шарм.:)