具有瞬态依赖性的 Aurelia 测试组件从不使用模拟
Aurelia testing components with transient dependencies never uses a mock
我们正在使用此处定义的 aurelia 组件测试(开玩笑):https://aurelia.io/docs/testing/components#testing-a-custom-element
我们正在测试的组件具有瞬态依赖性。我们正在为这个依赖创建一个 mock,但是当我们 运行 使用 au jest 进行测试时, 真实的总是被 DI 容器注入,而不是 mock.
这是临时服务:
import { transient } from "aurelia-framework";
@transient()
export class ItemService {
constructor() {
}
getItems(): void {
console.log('real item service');
}
}
这是 'Mock' 服务(我们也尝试过使用 jest mocks 但我们得到了相同的结果):
import { transient } from "aurelia-dependency-injection";
@transient()
export class MockItemService{
getItems():void {
console.log('mock item service');
}
}
这是被测组件:
import {ItemService} from "../services/item-service";
import { autoinject } from "aurelia-dependency-injection";
@autoinject()
export class TestElement {
constructor(private _itemService: ItemService) {
}
attached(): void {
this._itemService.getItems();
}
}
这是规范文件:
import {TestElement} from "../../src/resources/elements/test-element";
import {ComponentTester, StageComponent} from "aurelia-testing";
import {ItemService} from "../../src/resources/services/item-service";
import {MockItemService} from "./mock-item-service";
import {bootstrap} from "aurelia-bootstrapper";
describe('test element', () => {
let testElement;
const path: string = '../../src/resources/elements/test-element';
beforeEach(() => {
testElement = StageComponent.withResources(path).inView(`<test-element></test-element>`);
testElement.bootstrap(aurelia => {
aurelia.use.standardConfiguration();
aurelia.container.registerTransient(ItemService, MockItemService);
});
});
afterEach(() => {
testElement.dispose();
});
it('should call mock item service', async() => {
await testElement.create(bootstrap);
expect(testElement).toBeTruthy();
})
});
但每次测试都是 运行,控制台会注销真实服务而不是模拟服务。我已经将其追溯到 Container.prototype.get 函数中的 aurelia-dependency-injection.js 。问题似乎与这部分代码有关:
var registration = aureliaMetadata.metadata.get(aureliaMetadata.metadata.registration, key);
if (registration === undefined) {
return this.parent._get(key);
}
注册对象似乎有点奇怪,如果未定义,代码将工作,因为正确的依赖项已在父级上注册,并且它将获得模拟依赖项。但是,它不是未定义的,因此它在这一行的 DI 容器中注册了真正的服务:
return registration.registerResolver(this, key, key).get(this, key);
注册对象如下所示:
registration = TransientRegistration {_key = undefined}
这是 aurelia 中的错误还是我的操作有问题?
非常感谢
p.s。 GitHub 回购这里复制问题:https://github.com/Magrangs/aurelia-transient-dependency-issue
p.p.s 分叉了 DI 容器存储库并添加了一个快速修复程序,它可以解决我的特定问题,但不确定会产生什么连锁反应。如果aurelia团队的成员可以检查一下,那就太好了:
https://github.com/Magrangs/dependency-injection/commit/56c7d96a496e76f330a1fc3f9c4d62700b9ed596
在与 Rob Eisenberg 就此问题进行交谈后,有一个解决此问题的方法。首先删除 class 上的 @transient 装饰器,然后在您的应用启动时(通常是 main.ts)将 class 注册为瞬态。
在此处查看主题:
https://github.com/Magrangs/dependency-injection/commit/56c7d96a496e76f330a1fc3f9c4d62700b9ed596
我还更新了上面发布的回购协议:https://github.com/Magrangs/aurelia-transient-dependency-issue
包括修复。
希望这能帮助面临同样问题的任何其他开发者。
我们正在使用此处定义的 aurelia 组件测试(开玩笑):https://aurelia.io/docs/testing/components#testing-a-custom-element
我们正在测试的组件具有瞬态依赖性。我们正在为这个依赖创建一个 mock,但是当我们 运行 使用 au jest 进行测试时, 真实的总是被 DI 容器注入,而不是 mock.
这是临时服务:
import { transient } from "aurelia-framework";
@transient()
export class ItemService {
constructor() {
}
getItems(): void {
console.log('real item service');
}
}
这是 'Mock' 服务(我们也尝试过使用 jest mocks 但我们得到了相同的结果):
import { transient } from "aurelia-dependency-injection";
@transient()
export class MockItemService{
getItems():void {
console.log('mock item service');
}
}
这是被测组件:
import {ItemService} from "../services/item-service";
import { autoinject } from "aurelia-dependency-injection";
@autoinject()
export class TestElement {
constructor(private _itemService: ItemService) {
}
attached(): void {
this._itemService.getItems();
}
}
这是规范文件:
import {TestElement} from "../../src/resources/elements/test-element";
import {ComponentTester, StageComponent} from "aurelia-testing";
import {ItemService} from "../../src/resources/services/item-service";
import {MockItemService} from "./mock-item-service";
import {bootstrap} from "aurelia-bootstrapper";
describe('test element', () => {
let testElement;
const path: string = '../../src/resources/elements/test-element';
beforeEach(() => {
testElement = StageComponent.withResources(path).inView(`<test-element></test-element>`);
testElement.bootstrap(aurelia => {
aurelia.use.standardConfiguration();
aurelia.container.registerTransient(ItemService, MockItemService);
});
});
afterEach(() => {
testElement.dispose();
});
it('should call mock item service', async() => {
await testElement.create(bootstrap);
expect(testElement).toBeTruthy();
})
});
但每次测试都是 运行,控制台会注销真实服务而不是模拟服务。我已经将其追溯到 Container.prototype.get 函数中的 aurelia-dependency-injection.js 。问题似乎与这部分代码有关:
var registration = aureliaMetadata.metadata.get(aureliaMetadata.metadata.registration, key);
if (registration === undefined) {
return this.parent._get(key);
}
注册对象似乎有点奇怪,如果未定义,代码将工作,因为正确的依赖项已在父级上注册,并且它将获得模拟依赖项。但是,它不是未定义的,因此它在这一行的 DI 容器中注册了真正的服务:
return registration.registerResolver(this, key, key).get(this, key);
注册对象如下所示:
registration = TransientRegistration {_key = undefined}
这是 aurelia 中的错误还是我的操作有问题?
非常感谢
p.s。 GitHub 回购这里复制问题:https://github.com/Magrangs/aurelia-transient-dependency-issue
p.p.s 分叉了 DI 容器存储库并添加了一个快速修复程序,它可以解决我的特定问题,但不确定会产生什么连锁反应。如果aurelia团队的成员可以检查一下,那就太好了:
https://github.com/Magrangs/dependency-injection/commit/56c7d96a496e76f330a1fc3f9c4d62700b9ed596
在与 Rob Eisenberg 就此问题进行交谈后,有一个解决此问题的方法。首先删除 class 上的 @transient 装饰器,然后在您的应用启动时(通常是 main.ts)将 class 注册为瞬态。
在此处查看主题: https://github.com/Magrangs/dependency-injection/commit/56c7d96a496e76f330a1fc3f9c4d62700b9ed596
我还更新了上面发布的回购协议:https://github.com/Magrangs/aurelia-transient-dependency-issue
包括修复。
希望这能帮助面临同样问题的任何其他开发者。