模拟 Observable 以在 Jest 中抛出错误
Mocking Observable to throw error in Jest
我正在尝试模拟 Angular 的 HttpClient
的 PUT
调用以抛出错误。我为此使用 throwError
。它不工作。我应该更改什么以使其抛出错误并调用 handleError
方法? 我正在使用 Jest。
it(`should call the 'handleError' method when a request to store data was not successful`, () => {
const error: HttpErrorResponse = {
status: 401,
message: 'You are not logged in',
} as HttpErrorResponse;
jest.spyOn(httpClientServiceMock, 'put').mockReturnValue(throwError(error));
const spy = jest.spyOn(httpService, 'handleError');
httpService.requestCall('some-url', ApiMethod.PUT, {});
expect(spy).toBeCalled();
});
服务文件
requestCall(url: string, method: ApiMethod, data?: any): Observable<any> {
const headers = {
'X-XSRF-TOKEN': this.xsrfToken,
'Content-Type': 'application/json; charset=UTF-8',
};
const requestConfig = {
withCredentials: true,
headers,
};
switch (method) {
case ApiMethod.GET:
return this._http.get(url, { withCredentials: true });
case ApiMethod.PUT:
return this._http
.put(url, data, requestConfig)
.pipe(catchError((error) => this.handleError(error)));
}
}
handleError(error: HttpErrorResponse): any {
if (error.error instanceof ErrorEvent) {
console.error(`An error occurred: ${error.error.message}`);
}
return throwError({ error: error.message, status: error.status });
}
你们非常接近!
你必须subscribe to observable returned from httpService.requestCall('some-url', ApiMethod.PUT, {})
function. There are additional changes required as this is asynchronous
const { of , throwError, operators: {
catchError
}
} = rxjs;
const httpClientServiceMock = {
put: () => of ({
value: 'test'
})
};
const httpService = {
requestCall(url, data, requestConfig) {
return httpClientServiceMock
.put(url, data, requestConfig)
.pipe(catchError((error) => this.handleError(error)));
},
handleError(error) {
return throwError({});
}
};
const ApiMethod = {
PUT: ''
}
const {
expect,
test,
run,
it,
describe,
jest
} = jestLite.core;
describe('httpService', () => {
it(`should call the 'handleError' method when a request to store data was not successful`, done => {
const error = {
status: 401,
message: 'You are not logged in',
}
jest.spyOn(httpClientServiceMock, 'put').mockReturnValue(throwError(error));
const spy = jest.spyOn(httpService, 'handleError');
httpService
.requestCall('some-url', ApiMethod.PUT, {})
.subscribe(pr => {
done.fail(new Error(`It shouldn't go this path!`))
}, error => {
expect(spy).toBeCalled();
done();
});
});
});
run().then(result => {
console.log(result[0]);
})
<script src="https://cdn.jsdelivr.net/npm/jest-lite@1.0.0-alpha.4/dist/core.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.5/rxjs.umd.js"></script>
正如其他答案中已经指出的那样,您必须订阅返回的可观察对象。
我只是想添加另一种使用 marble-testing 的方法,因此您不必手动订阅该可观察对象:
let testScheduler;
beforeEach(() => testScheduler = new TestScheduler(assertionFn))
it(`should call the 'handleError' method when a request to store data was not successful`, () => {
const error = {
status: 401,
message: 'You are not logged in',
} as HttpErrorResponse;
jest.spyOn(httpClientServiceMock, 'put').mockReturnValue(throwError(error));
const spy = jest.spyOn(httpService, 'handleError');
testScheduler.run(({ cold, expectObservable }) => {
const src$ = httpService.requestCall('some-url', ApiMethod.PUT, {});
expectObservable(src$).toBe('#', null, { error: error.message, status: error.status });
expect(spy).toBeCalled();
});
});
TestScheduler
在 rxjs/testing
中可用,run
的回调提供了几个助手,例如:cold
、hot
、flush
、expectObservable
、expectSubscriptions
和 time
.
我个人喜欢的一点是一切都是同步的,因此在采用这种方法时您可能不必调用 done()
。
我正在尝试模拟 Angular 的 HttpClient
的 PUT
调用以抛出错误。我为此使用 throwError
。它不工作。我应该更改什么以使其抛出错误并调用 handleError
方法? 我正在使用 Jest。
it(`should call the 'handleError' method when a request to store data was not successful`, () => {
const error: HttpErrorResponse = {
status: 401,
message: 'You are not logged in',
} as HttpErrorResponse;
jest.spyOn(httpClientServiceMock, 'put').mockReturnValue(throwError(error));
const spy = jest.spyOn(httpService, 'handleError');
httpService.requestCall('some-url', ApiMethod.PUT, {});
expect(spy).toBeCalled();
});
服务文件
requestCall(url: string, method: ApiMethod, data?: any): Observable<any> {
const headers = {
'X-XSRF-TOKEN': this.xsrfToken,
'Content-Type': 'application/json; charset=UTF-8',
};
const requestConfig = {
withCredentials: true,
headers,
};
switch (method) {
case ApiMethod.GET:
return this._http.get(url, { withCredentials: true });
case ApiMethod.PUT:
return this._http
.put(url, data, requestConfig)
.pipe(catchError((error) => this.handleError(error)));
}
}
handleError(error: HttpErrorResponse): any {
if (error.error instanceof ErrorEvent) {
console.error(`An error occurred: ${error.error.message}`);
}
return throwError({ error: error.message, status: error.status });
}
你们非常接近!
你必须subscribe to observable returned from httpService.requestCall('some-url', ApiMethod.PUT, {})
function. There are additional changes required as this is asynchronous
const { of , throwError, operators: {
catchError
}
} = rxjs;
const httpClientServiceMock = {
put: () => of ({
value: 'test'
})
};
const httpService = {
requestCall(url, data, requestConfig) {
return httpClientServiceMock
.put(url, data, requestConfig)
.pipe(catchError((error) => this.handleError(error)));
},
handleError(error) {
return throwError({});
}
};
const ApiMethod = {
PUT: ''
}
const {
expect,
test,
run,
it,
describe,
jest
} = jestLite.core;
describe('httpService', () => {
it(`should call the 'handleError' method when a request to store data was not successful`, done => {
const error = {
status: 401,
message: 'You are not logged in',
}
jest.spyOn(httpClientServiceMock, 'put').mockReturnValue(throwError(error));
const spy = jest.spyOn(httpService, 'handleError');
httpService
.requestCall('some-url', ApiMethod.PUT, {})
.subscribe(pr => {
done.fail(new Error(`It shouldn't go this path!`))
}, error => {
expect(spy).toBeCalled();
done();
});
});
});
run().then(result => {
console.log(result[0]);
})
<script src="https://cdn.jsdelivr.net/npm/jest-lite@1.0.0-alpha.4/dist/core.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.5/rxjs.umd.js"></script>
正如其他答案中已经指出的那样,您必须订阅返回的可观察对象。
我只是想添加另一种使用 marble-testing 的方法,因此您不必手动订阅该可观察对象:
let testScheduler;
beforeEach(() => testScheduler = new TestScheduler(assertionFn))
it(`should call the 'handleError' method when a request to store data was not successful`, () => {
const error = {
status: 401,
message: 'You are not logged in',
} as HttpErrorResponse;
jest.spyOn(httpClientServiceMock, 'put').mockReturnValue(throwError(error));
const spy = jest.spyOn(httpService, 'handleError');
testScheduler.run(({ cold, expectObservable }) => {
const src$ = httpService.requestCall('some-url', ApiMethod.PUT, {});
expectObservable(src$).toBe('#', null, { error: error.message, status: error.status });
expect(spy).toBeCalled();
});
});
TestScheduler
在 rxjs/testing
中可用,run
的回调提供了几个助手,例如:cold
、hot
、flush
、expectObservable
、expectSubscriptions
和 time
.
我个人喜欢的一点是一切都是同步的,因此在采用这种方法时您可能不必调用 done()
。