Phi*_*hil 7 unit-testing karma-runner karma-jasmine angular
如何在 Angular 中模拟 DOCUMENT(HTMLDocument 的影子表示)?实现是在构造函数中使用 this:
@Inject(DOCUMENT) private document: Document
Run Code Online (Sandbox Code Playgroud)
在查看了如何在 Angular 2 服务中注入文档后,我已将其放入我的 .spec 设置中:
const lazyPath = 'dummy';
const pathname = `/${lazyPath}`;
const document = { location: { pathname } as Location } as Document;
beforeEachProviders(() => ([ {provide: DOCUMENT, useValue: document} ]));
Run Code Online (Sandbox Code Playgroud)
但这给了我错误:
ERROR in ./src/app/main/components/app-lazy/app-lazy.component.spec.ts
Module not found: Error: Can't resolve '@angular/core/testing/src/testing_internal' in '...'
resolve '@angular/core/testing/src/testing_internal' in '....'
Parsed request is a module
using description file: .../package.json (relative path: ...)
Field 'browser' doesn't contain a valid alias configuration
resolve as module
Run Code Online (Sandbox Code Playgroud)
当我在 TestBed.configureTestingModule 中使用简单的提供程序:[]而不是testing_internal包中的beforeEachProviders时,该组件未定义,例如未正确初始化。当我从注入的文档切换到窗口对象(我无法在其上设置/模拟位置)时,它仅在单元测试中初始化(在非测试执行中都有效)。我能做些什么?
您应该避免模拟整个文档对象并模拟/监视其上的单个方法/属性。
假设您的组件/服务中有以下内容:
import { DOCUMENT } from '@angular/common';
...
constructor(@Inject(DOCUMENT) private document: Document) {}
Run Code Online (Sandbox Code Playgroud)
您可以通过将文档对象注入到您的beforeEach
describe('SomeComponent', () => {
let component: SomeComponent;
let doc: Document;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [SomeComponent],
imports: [
RouterTestingModule,
HttpClientTestingModule
]
});
const fixture = TestBed.createComponent(AppComponent);
component = fixture.componentInstance;
doc = TestBed.inject(DOCUMENT); // Inject here **************
});
it('set document title', () => {
component.setPageTitle('foobar'); // Assuming this component method is `this.document.title = title`
expect(doc.title).toBe('foobar');
});
it('calls querySelectorAll', () => {
const spy = spyOn(doc, 'querySelectorAll');
component.someMethodThatQueries();
expect(spy).toHaveBeenCalled();
});
});
Run Code Online (Sandbox Code Playgroud)
我很可能遇到与@Phil类似的问题。该问题似乎与将 DOCUMENT 注入组件有关。
当您模拟注入的 DOCUMENT 时,在内部调用 时,调用TestBed.createComponent()会引发错误document.querySelectorAll()。
TestBed.createComponent()似乎正在访问注入的模拟文档对象。不确定这是一个错误还是有意为之。
我最近遇到了 Angular 11 的问题。因为我懒得建立一个新的 stackblitz,所以我在基于 Angular 8 的现有 stackblitz 上复制了它。但问题是一样的。
https://stackblitz.com/edit/jasmine-in-angular-beomut?file=src%2Fapp%2Fapp.component.spec.ts
我当前针对此问题的解决方案/解决方法是:
将相关逻辑移至document服务中。在那里可以轻松地测试它,而无需调用TestBed.createComponent()。然后,您可以在您的组件中模拟该服务。
将此作为答案发布,因为格式在评论中不起作用。
如果可能的话,你能分享一下 stackblitz 吗?当我需要注入模拟时,我通常将其设置为:
// ... beginning of file
const mockDocument = { location: { pathname } };
beforeEach(() => TestBed.configureTestingModule({
imports: [...],
// Provide DOCUMENT Mock
providers: [
{ provide: DOCUMENT, useValue: mockDocument }
]
}));
// ...rest of file
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
17813 次 |
| 最近记录: |