【发布时间】:2020-11-25 13:06:52
【问题描述】:
我编写了一个实现来从 API 调用中获取数据。但是,在测试功能时,我什至在编写任何有意义的测试用例之前就遇到了以下错误:
TypeError: Cannot read property 'subscribe' of undefined
at DataComponent.ngOnInit (http://localhost:9876/_karma_webpack_/webpack:/src/app/dashboard/job/job.component.ts:48:10)
at callHook (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:3405:1)
at callHooks (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:3375:1)
at executeInitAndCheckHooks (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:3327:1)
at refreshView (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:8573:1)
at renderComponentOrTemplate (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:8672:1)
at tickRootContext (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:9885:1)
at detectChangesInRootView (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:9910:1)
at RootViewRef.detectChanges (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:10320:1)
at ComponentFixture._tick (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/__ivy_ngcc__/fesm2015/testing.js:243:1)
我不确定我错过了什么,任何帮助将不胜感激。 我研究了以下内容以获得一些理解:
- Why am I getting a "Failed: Cannot read property 'subscribe' of undefined" while running tests? -> 解决方案在我的情况下不起作用
- karma TypeError "Cannot read property 'subscribe' of undefined"
以及其他一些参考资料。
这是我的代码文件。我已经删除了我认为与当前问题无关的某些代码部分。
dataService.ts 代码:
import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { IData } from '../model/data.model';
import { Observable, throwError } from 'rxjs';
import {catchError, tap} from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class DataService {
constructor(private http: HttpClient) { }
public getData(): Observable<IData[]>{
return this.http.get<IData[]>('url')
.pipe(
tap(data => console.log('Data Received')),
catchError(this.handleError)
);
}
private handleError(err: HttpErrorResponse){
//handle error code
}
}
我正在测试的组件 -> data.component.ts 代码:
import { Component, OnInit, Input} from '@angular/core';
import { IData } from '../../model/data.model';
import {DataService} from '../../service/data.service';
@Component({
selector: 'app-job',
templateUrl: './job.component.html',
styleUrls: ['./job.component.css']
})
export class JobComponent implements OnInit {
@Input() appId: string;
jobs: IData[] = [];
constructor( private dataService: DataService ) {}
ngOnInit(): void {
this.dataService.getData().subscribe({
next: data => {
this.data = data;
},
error: err => this.errorMessage = err
});
}
//other implementation
}
测试文件:data.spec.ts:
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { DataComponent } from './job.component';
import { IData } from 'src/app/model/job.model';
import { DataService } from 'src/app/service/job-data.service';
import { of, Observable } from 'rxjs';
import { NO_ERRORS_SCHEMA } from '@angular/core';
describe('DataComponent', () => {
let component: DataComponent;
let fixture: ComponentFixture<DataComponent>;
let mockDataService ;
let JOBS: IData[];
beforeEach(async () => {
mockJobDataService = jasmine.createSpyObj(['getData']);
await TestBed.configureTestingModule({
declarations: [ DataComponent ],
providers: [
{provide: DataService, useValue: mockDataService}
]
})
.compileComponents()
.then(() => {
DATA = [{id: 'CJH'}];
fixture = TestBed.createComponent(DataComponent);
component = fixture.componentInstance;
fixture.detectChanges(); //updates bindings
});
});
it('should return true',() => {
expect(true).toBe(true);
})
});
当我删除 fixture.detectChanges() 时,错误被删除。但据我了解,即使我在测试中的任何地方使用此调用,测试用例也应该可以工作。
【问题讨论】:
-
为错误道歉。为了发布问题,我更改了组件和变量的名称,但遗漏了一些地方。将所有出现的“工作”替换为“数据”。 (如 JobComponent->DataComponent、JOBS->DATA 等)
-
你为什么不为你的'mockDataService'模拟值定义一个'getData'假实现?
-
@habibchabbi 你是这个意思吗? mockDataService= { getData: () => {return of(DATA);} }
-
是的,这行不通?
-
是的,它现在可以工作了。我之前犯了一个愚蠢的错误。谢谢
标签: javascript angular typescript rxjs integration-testing