如何模拟 Angular 外部 Javascript 对象
How to mock Angular external Javascript object
我有一个 angular 应用程序,其唯一目的是构建 @angular/elements(没有 index.html,没有 app.component,等等)。
这些元素在 .NET Mvc 应用程序中使用,它提供了两种我试图在我的单元测试中模拟的东西:
1 - 外部图书馆
例如JQuery、lodash等
2 - 客户端框架"foo"
在包含我的 Web 元素的 .NET MVC 视图中,MVC 应用程序创建了一个名为 foo 的对象。该对象不是 ES6 模块。它是用漂亮的 foo = new Foo({ someOptionsGeneratedFromServerSide});
手动创建的
这两种情况都在我的网络元素中使用。例如,一个组件将使用函数 foo.displayAlert('With a message')。
我发现使我的 angular 应用程序符合该要求的唯一解决方案是添加以下内容:
// tslint:disable-next-line: max-line-length no-reference
/// <reference path='path/to/the/definition.d.ts' />
我知道这很不正统。
Angular 应用程序工作正常,直到我尝试进行一些单元测试。
注意:它不能单独工作(ng serve 果然没用)
一个例子
it('should render title', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.nativeElement;
expect(compiled.querySelector('.content span').textContent).toContain('ng-jest app is running!');
});
对于这个组件/钩子:
ngOnInit() {
foo.displayAlert('With a message');
}
将崩溃并显示以下(意料之中的)消息:
AppComponent › should render title
ReferenceError: foo is not defined
我试图在测试前显式模拟对象:
let foo: any;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
RouterTestingModule
],
declarations: [
AppComponent
],
}).compileComponents();
foo = {
displayAlert: Function
};
}));
到目前为止运气不好。我在 x.spect.ts 中针对此对象做了很多尝试,但没有结果。
我试图用 index.html 创建另一个 Angular 应用程序,其中包括 MVC 视图等所有资源,但失败了。
最后的笔记
对于 JQuery / lodash 这样的第 3 方,我不想将它们添加到我的 Angular 项目中,例如:
npm i -D lodash
因为我不希望它们包含在我的 vendor.js 文件中。这些库由 .Net Mvc 应用程序提供,这很好。
这也适用于 foo 对象。
最后,我尝试使用 (Jest) 和不使用 (Karma) 的无头浏览器进行测试。
非常感谢任何帮助!
编辑 2020 年 3 月 27 日
求求你救救我!
编辑 2020 年 3 月 28 日
尝试了 jasmine.createSpyObject & spyOn,也没有运气:(
复杂的设置,你自己做起来并不容易。
但是,您似乎只需要将 foo
伪造为全局变量,因为全局范围是您的组件期望变量所在的位置。当您在 ECMAScript 模块中声明 let foo
时,您正在创建一个作用域为您的组件无法访问的文件的变量。
beforeEach(() => {
window.foo = {
displayAlert: () => {},
};
});
这可能会让您与 TypeScript 纠缠不清。快速修复是这个
beforeEach(() => {
(window as any).foo = {
displayAlert: () => {},
};
});
我有一个 angular 应用程序,其唯一目的是构建 @angular/elements(没有 index.html,没有 app.component,等等)。
这些元素在 .NET Mvc 应用程序中使用,它提供了两种我试图在我的单元测试中模拟的东西:
1 - 外部图书馆
例如JQuery、lodash等
2 - 客户端框架"foo"
在包含我的 Web 元素的 .NET MVC 视图中,MVC 应用程序创建了一个名为 foo 的对象。该对象不是 ES6 模块。它是用漂亮的 foo = new Foo({ someOptionsGeneratedFromServerSide});
手动创建的这两种情况都在我的网络元素中使用。例如,一个组件将使用函数 foo.displayAlert('With a message')。 我发现使我的 angular 应用程序符合该要求的唯一解决方案是添加以下内容:
// tslint:disable-next-line: max-line-length no-reference
/// <reference path='path/to/the/definition.d.ts' />
我知道这很不正统。
Angular 应用程序工作正常,直到我尝试进行一些单元测试。 注意:它不能单独工作(ng serve 果然没用)
一个例子
it('should render title', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.nativeElement;
expect(compiled.querySelector('.content span').textContent).toContain('ng-jest app is running!');
});
对于这个组件/钩子:
ngOnInit() {
foo.displayAlert('With a message');
}
将崩溃并显示以下(意料之中的)消息:
AppComponent › should render title
ReferenceError: foo is not defined
我试图在测试前显式模拟对象:
let foo: any;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
RouterTestingModule
],
declarations: [
AppComponent
],
}).compileComponents();
foo = {
displayAlert: Function
};
}));
到目前为止运气不好。我在 x.spect.ts 中针对此对象做了很多尝试,但没有结果。
我试图用 index.html 创建另一个 Angular 应用程序,其中包括 MVC 视图等所有资源,但失败了。
最后的笔记
对于 JQuery / lodash 这样的第 3 方,我不想将它们添加到我的 Angular 项目中,例如:
npm i -D lodash
因为我不希望它们包含在我的 vendor.js 文件中。这些库由 .Net Mvc 应用程序提供,这很好。
这也适用于 foo 对象。
最后,我尝试使用 (Jest) 和不使用 (Karma) 的无头浏览器进行测试。
非常感谢任何帮助!
编辑 2020 年 3 月 27 日
求求你救救我!
编辑 2020 年 3 月 28 日
尝试了 jasmine.createSpyObject & spyOn,也没有运气:(
复杂的设置,你自己做起来并不容易。
但是,您似乎只需要将 foo
伪造为全局变量,因为全局范围是您的组件期望变量所在的位置。当您在 ECMAScript 模块中声明 let foo
时,您正在创建一个作用域为您的组件无法访问的文件的变量。
beforeEach(() => {
window.foo = {
displayAlert: () => {},
};
});
这可能会让您与 TypeScript 纠缠不清。快速修复是这个
beforeEach(() => {
(window as any).foo = {
displayAlert: () => {},
};
});