我正在尝试为使用服务执行 HTTP 请求以从数据库中检索信息的组件设置一些单元测试。我对角度和单元测试非常陌生,所以请耐心等待。在我的测试中,我试图监视名为的函数getClients
(该函数本质上是实际执行 HTTP 请求的服务的处理程序)并使用callFake
.
我遇到的问题是该getClients
功能没有被覆盖,这使我相信间谍不起作用或没有监视我认为的内容。我可以说它没有被调用,因为失败消息引用了真实getClients
函数中的某些内容。
测试代码:
我的理解是,因为我试图监视的函数在ngOnInit
函数中,所以我必须先定义间谍,然后实例化组件。我也试过在里面运行间谍it
,但也没有用。
describe('handleID', () => {
beforeEach(waitForAsync (() => {
spyOn(service, 'getClients').and.callFake(() => {
let companyList = [
{
COMPANYDESCRIPTOR: "Hello World Inc.",
COMPANYNAME: "Hello World Inc.",
CUSTOMERID: "abcdef123456",
CUSTOMERKEY: 123456
}
]
component.companySearchService.companies.next(companyList);
return companyList;
});
fixture = TestBed.createComponent(CompanySearchComponent);
component = fixture.componentInstance;
service = component.companySearchService;
fixture.detectChanges();
}));
it("should update component.companyForm.controls['selectedCompany'] to 'Hello World Inc.'", () => {
component.companyForm = component._formBuilder.group({
selectedCompany: ['']
})
component.pathToNameProp = 'COMPANYNAME';
component.pathToIdProp = ['CUSTOMERID', 'CUSTOMERKEY'];
let id = 123456;
component.handleID(id);
expect(component.companyForm.get('selectedCompany')).toBe('Hello World Inc.');
})
})
实际功能:
为了清楚起见,我提供了getClients
以下功能。dbService
是进行 API 调用的数据库服务。makeAnApiCall
返回一个observable
并且subscribe
只是将数据传递给另一个处理程序,该处理程序根据source
.
getClients(endpoint, method, options = []) {
this.loading.next(true);
this.dbService
.makeAnApiCall(endpoint, method, options)
.subscribe(
res => this.generateCompanyList(res, this.source.getValue())
)
}
失败消息:
失败消息引用了从数据库服务的makeAnApiCall
方法返回的可观察订阅。这让我相信间谍根本不是被创造出来的,或者完全是在监视其他东西。
Failed: Cannot read properties of undefined (reading 'subscribe')
at CompanySearchService.getClients (http://localhost:9876/_karma_webpack_/main.js:6343:13)
at CompanySearchComponent.ngOnInit (http://localhost:9876/_karma_webpack_/webpack:/src/app/utilities/company-search/company-search.component.ts:98:39)
...
问题:
提前感谢您的任何帮助!
这个解决方案解决了我的问题,但它仍然没有真正回答我的问题。因此,如果有人可以对此有所了解,我很乐意将他们的回答标记为已接受的答案。
单元测试
它看起来像我调用spyOn
,的顺序fixture.detectChanges
,并且component.ngOnInit
弄乱了服务,因此弄乱了我的Cannot read properties of undefined
错误。下面更新的代码是完整的单元测试。我创建了__beforeEach
这样我就不必重复嵌套单元测试中的所有内容。我最终也完全取消了调用component.ngOnInit()
,因为它似乎detectChanges
也同样有效。
describe('CompanySearchComponent', () => {
let fixture, component, service;
let __beforeEach = () => {
fixture = TestBed.createComponent(CompanySearchComponent);
component = fixture.componentInstance;
service = component.companySearchService;
component.companySource = 'database';
spyOn(service, 'getClients').and.callFake(() => {
let response = { data: { rows:[
{
COMPANYDESCRIPTOR: "Hello World Inc.",
COMPANYNAME: "Hello World Inc.",
CUSTOMERID: "abcdef123456",
CUSTOMERKEY: 123456
}
]}}
component.companySearchService.generateCompanyList(response, 'database');
});
fixture.detectChanges();
}
beforeAll(waitForAsync(__beforeEach));
it ('should initialize the component and the service', () => {
expect(component).toBeDefined();
expect(service).toBeDefined();
})
it ('should initalize pathToNameProp to \'COMPANYNAME\' and pathToProp to [\'CUSTOMERID\', \'CUSTOMERKEY\'] with source set to \'database\'', () => {
expect(component.pathToNameProp).toBe('COMPANYNAME');
expect(component.pathToIdProp).toEqual(['CUSTOMERID', 'CUSTOMERKEY']);
})
it ('should update companies array', () => {
expect(component.companies).toEqual([
{
COMPANYDESCRIPTOR: "Hello World Inc.",
COMPANYNAME: "Hello World Inc.",
CUSTOMERID: "abcdef123456",
CUSTOMERKEY: 123456
}
]);
})
describe('handleID', () => {
beforeAll(waitForAsync(__beforeEach));
it("should update selectedCompany form'", () => {
let id = '123456';
component.handleID(id);
expect(component.companyForm.controls['selectedCompany'].value.COMPANYNAME).toBe('Hello World Inc.');
})
})
})
设置源
它可能不相关,但我想提出另一个我遇到的问题。该组件不是独立的,其他组件将其作为依赖项导入。也就是说,必须显式定义companySearchComponent.companySource
然后重新初始化组件,因为它的值是在构造函数中定义的。
constructor(
private elem: ElementRef,
public companySearchService: CompanySearchService,
private hierarchyService: HierarchyService,
private _formBuilder: FormBuilder
) {
this.companySource = this.elem.nativeElement.dataset.companySrc;
this.prevCompanySrc = this.companySearchService.source.getValue();
}
构造函数引用源的选择器元素
<company-search [hidden]="!showSearch" id="company-search" data-company-src="database"></company-search>
在companySearchComponent.ngOnInit
该源值内部,用于定义 http 请求和响应的一些重要属性。它也用于初始调用companySearchService.getClients()
(我最初遇到问题的函数)。
ngOnInit() {
switch(this.companySource) {
case 'database':
...
this.pathToNameProp = 'COMPANYNAME';
this.pathToIdProp = ['CUSTOMERID', 'CUSTOMERKEY'];
break;
...
default:
break;
}
if (!this.companySearchService.companies.value || this.prevCompanySrc !== this.companySource) {
this.companySearchService.source.next(this.companySource);
this.companySearchService.getClients(this.endpoint, this.httpMethod, this.httpOptions);
}
...
}
就像我说的那样,这并不能完全回答我提出的问题,但它是解决问题的方法,所以如果有人发布更全面和彻底的解决方案,我很乐意将其标记为已接受的答案。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句