角单元测试失败HttpClient请求
问题描述:
我试图单元测试一个服务,我有可以响应http调用。我可以测试成功请求,但是当响应的状态代码与200不同时,我无法进行测试。角单元测试失败HttpClient请求
例如,让我们假设请求返回404状态,然后我无法正确测试。
这是我的服务:
@Injectable()
export class ApiService {
constructor(
private _http: HttpClient,
private _router: Router,
private _toast: ToastsManager,
private _auth: AuthService,
) { }
public apiGet(url: string) {
return this._http
.get(url)
.catch(this.handleError.bind(this));
}
private handleError(error) {
if (error.status === 401) {
this._auth.logout();
return Observable.throw(error);
}
if (error.status === 404) {
this._router.navigateByUrl('not-found');
return Observable.throw(error);
}
if (error.error && error.error.message) {
this._toast.error(error.error.message);
} else {
this._toast.error('Something went wrong');
}
return Observable.throw(error);
}
}
这就是我是如何测试:
describe('ApiService',() => {
let service: ApiService;
let backend: HttpTestingController;
const mockSuccessResponse = { value: '123', name: 'John' };
const mockSuccessStatus = { status: 200, statusText: 'Ok' };
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
MockModule,
HttpClientTestingModule,
],
providers: [
ApiService,
]
});
service = TestBed.get(ApiService);
backend = TestBed.get(HttpTestingController);
});
it('should call the apiGet() function with success',() => {
service.apiGet('mock/get/url').subscribe(response => {
expect(response).toEqual(mockSuccessResponse);
});
const req = backend.expectOne('mock/get/url');
expect(req.request.url).toBe('mock/get/url');
expect(req.request.method).toBe('GET');
req.flush(mockSuccessResponse, mockSuccessStatus);
});
it('should execute handleError function on status different of 200',() => {
service.apiGet('mock/error/url').subscribe(response => { }, error => {
// Handle the error cases here (?)
});
const req = backend.expectOne('mock/error/url');
req.flush(null, { status: 404, statusText: 'Not Found' });
});
afterEach(() => {
backend.verify();
});
});
我不知道如何从这里继续。如果我尝试执行类似expect(service.handleError()).toHaveBeenCalled();
的操作,我会收到类似handleError is a private method
的错误。
我还需要测试authService
上的函数logout()
是否会被调用,或者如果路径更改为not-found
404错误。
我应该怎么做才能测试这些情况,其中响应的状态不同于200?
答
我解决这个问题的方法是测试handleError函数是否被调用,然后创建另一组测试来单独测试handleError函数。
it('should execute handleError function on status different of 200',() => {
// "as any" to avoid the "private method" type errors
spyOn(service as any, 'handleError');
service.apiGet('mock/get/url').subscribe(() => { }, error => {
// This is where I just check if the function was called
// It also needs to be service['handleError'] to avoid type errors on private method
expect(service['handleError']).toHaveBeenCalled();
});
const req = backend.expectOne('mock/get/url');
req.flush(null, { status: 400, statusText: 'Error' });
});
然后,我创建另一组测试,我手动设置我试图测试,404例如错误代码:
it('should navigate to route "not-found" on status 404',() => {
spyOn(router, 'navigateByUrl');
const mockError = {
status: 404,
error: {
message: 'Page not found',
},
};
service['handleError'](mockError);
// Here we adapt to test whatever condition it is
// Mine is a simple redirect to an error page
expect(router.navigateByUrl).toHaveBeenCalledWith('not-found');
});