在 Angular / Jasmine 单元测试中 spyService 和 throwError() 的问题;



我在模拟在组件的单元测试文件中返回错误的服务时遇到问题。我的应用程序是用 Angular 6 和 TypeScript 编写的,我的单元测试是用 Jasmine 编写的。

在我的组件中,我在ngOnInit中调用一个方法,在此方法中,我在导入的服务上调用一个方法,如果失败,我的组件的布尔属性称为isLoading应设置为 false。以下是我的组件的一些最小化代码,以便了解我希望测试的代码。

export class CylindersListComponent implements OnInit, OnDestroy {
public isLoading: boolean = true;
public ngOnInit(): void {
// do stuff ... I have removed some code here
this.loadCylinderList();
}
public loadCylinderList() {
this.cylindersService.getCylinderList().subscribe((res: any) => {
this.cylinders = res;
// do stuff ... I have removed lots of code here
this.isLoading = false;
}, (error: any) => {
this.isLoading = false;
throw new Error(error);
});
}
}

我想模拟正在调用的loadCylinderList方法和返回错误的cylindersService.getCylinderList。因此,一旦完成此操作,我希望断言(或确保(isLoading属性是错误的。现在我像这样设置了我的单元测试,但这似乎不起作用(或者更有可能我错误地实现了测试(。我再次最小化了代码或...返回数据的位置。

describe('CylindersListComponent', () => {
let fixture: ComponentFixture<CylindersListComponent>;
let instance: CylindersListComponent;
const spyCylinderService = jasmine.createSpyObj<CylindersService>(
'CylindersService', ['getCylinderList', 'getListPaged']);
spyCylinderService.getListPaged.and.returnValue(observedData); // observedData is set earler in the file 

beforeEach(async(() => {
// inject the spies. We use override component because the service is injected
// in component not in the module. (deeper level)
TestBed.overrideComponent(CylindersListComponent, {
set: {
providers: [
{provide: CylindersService, useValue: spyCylinderService}
],
template: '<input #filter>'
}
})
// prepare CylinderComponent for the tests
// Allows overriding default providers, directives, pipes
.configureTestingModule({
imports: [...],
declarations: [
CylindersListComponent
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
.compileComponents().then(() => {
// arrange
fixture = TestBed.createComponent(CylindersListComponent);
instance = fixture.componentInstance;
spyCylinderService.getCylinderList.and.returnValue({...});
});
}));
it('should be false after error while loading data', () => {
// arrange
spyCylinderService.getCylinderList.and.throwError('error');
instance.isLoading = true;
spyOn(instance, 'loadCylinderList' as any).and.callThrough();
// act
fixture.detectChanges();
expect(instance.isLoading).toBe(false);
});

这听起来像是一个非常开放的问题,我很抱歉,但我的测试/spyOn方法做错了什么。我确定我遇到了失败的测试/错误,因为我提出/模拟错误的实现不正确:spyCylinderService.getCylinderList.and.throwError('error');

如果有人能看到我做错了什么,我将不胜感激。如果有任何帮助,来自测试控制台的错误如下所示:

HeadlessChrome 0.0.0 (Mac OS X 10.12.6) CylindersListComponent isLoading should be false after error while loading data FAILED
Error: error
error properties: Object({ ngDebugContext: DebugContext_({ view: Object({ def: Object({ factory: Function, nodeFlags: 33800449, rootNodeFlags: 33554433, nodeMatchedQueries: 0, flags: 0, nodes: [ Object({ nodeIndex: 0, parent: null, renderParent: null, bindingIndex: 0, outputIndex: 0, checkIndex: 0, flags: 33554433, childFlags: 246016, directChildFlags: 246016, childMatchedQueries: 0, matchedQueries: Object({  }), matchedQueryIds: 0, references: Object({  }), ngContentIndex: null, childCount: 4, bindings: [  ], bindingFlags: 0, outputs: [  ], element: Object({ ns: '', name: 'cylinders', attrs: [  ], template: null, componentProvider: Object({ nodeIndex: 4, parent: <circular reference: Object>, renderParent: <circular reference: Object>, bindingIndex: 0, outputIndex: 0, checkIndex: 4, flags: 245760, childFlags: 0, directChildFlags: 0, childMatchedQueries: 0, matchedQueries: Object, matchedQueryIds: 0, references: Object, ngContentIndex: -1, childCount: 0, bindings: Array, bindingFlags: 0, outputs: Array,  ...
at <Jasmine>

更新:我确定我引发错误的方式是错误的,就好像我应该在捕获错误的组件中放置一个console.log,没有任何东西写入控制台。

原因可能是 isLoad 是异步更新的。因此,您应该等到所有更改检测和更新结束。

it('should be false after error while loading data', async(() => {
// arrange
spyCylinderService.getCylinderList.and.returnValue(Observable.throw('error'));
instance.isLoading = true;
spyOn(instance, 'loadCylinderList' as any).and.callThrough();
// act
fixture.detectChanges();
fixture.whenStable()
.then(() =>{
expect(instance.isLoading).toBe(false);
});    
}));

最新更新