[英]Testing an Angular service method which returns an Observable
我正在尝试让以下 Angular 12.6 服务的所有线路都变为绿色:我有这个测试组
describe('AuthService', () => {
let service: AuthService;
let apiResponse: ApiResponse;
let controller: HttpTestingController;
let accountDetails: AccountDetails;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: AuthInterceptor,
multi: true,
},
{ provide: APP_CONFIG, useValue: AppConfig },
],
});
service = TestBed.inject(AuthService);
controller = TestBed.inject(HttpTestingController);
apiResponse = {
accessToken: 'Gimme access'
};
accountDetails = {
Password: 'bla',
UserName: 'vlad',
};
});
/// a few other tests below
it('should call the back-end', () => {
spyOn(service, 'setSession');
spyOn(service, 'login').and.callThrough();
service.login(accountDetails.UserName, accountDetails.Password).subscribe(() => {
expect(service.setSession).toHaveBeenCalled();
});
expect(service.login).toHaveBeenCalledOnceWith('vlad', 'bla');
controller.match(AppConfig.apiEndPoint);
});
});
这作为服务方法:
@Injectable({
providedIn: 'root',
})
export class AuthService {
#storage = localStorage;
options = new HttpHeaders({
'Content-Type': 'application/json',
});
private static handleError(error: HttpErrorResponse) {
if (error.status === 0) {
// A client-side or network error occurred. Handle it accordingly.
console.error('An error occurred:', error.error);
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong.
console.error(`Backend returned code ${error.status}, body was: `, error.error);
}
// Return an observable with a user-facing error message.
return throwError('Something happened; please try again later.');
}
constructor(@Inject(APP_CONFIG) private config: IapConfig, private http: HttpClient) {}
login(customerKey: string, username: string, password: string): Observable<any> {
const timestamp = new Date().getTime();
return this.http
.post<AccountDetails>(this.config.apiEndPoint, {
Password: password,
UserName: username,
})
.pipe(catchError(AuthService.handleError))
.pipe(map((response: AccountDetails) => {
this.setSession(response);
return response;
}))
}
setSession(data: ApiResponse | any): void {
try {
// tslint:disable-next-line:no-console
console.info('User session is set 😁');
} catch (error) {
throw new Error(`Incorrect response structure. Unable to map: ${error}`);
}
}
}
一:不知何故,我感觉我并没有真正测试login
方法中的setSession
方法调用。 第二我如何测试 catch 块中的行?
我如何在没有 mocking 的情况下模拟测试通过 pipe 运算符登录返回的 Observable。 我无法模拟和检查的登录方法订阅下的 setSession 是用正确的 arguments 调用的。
在阅读了@AliF50推荐的测试文章 Angular - 测试服务后,我感谢他。 我在我的测试文件中提出了以下内容:
import { TestBed } from '@angular/core/testing';
import { AuthService } from './auth.service';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { APP_CONFIG, AppConfig } from '../app.config';
import { AccountDetails, ApiResponse } from '../interfaces';
describe('AuthService', () => {
let service: AuthService;
let apiResponse: ApiResponse;
let controller: HttpTestingController;
let accountDetails: AccountDetails;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [
AuthService,
{ provide: APP_CONFIG, useValue: AppConfig },
],
});
service = TestBed.inject(AuthService);
controller = TestBed.inject(HttpTestingController);
apiResponse = {
accessToken: 'Gimme access',
languageCode: 'EN',
};
accountDetails = {
Password: 'bla',
UserName: 'vlad',
TimeStamp: '123454',
};
});
it('should call the back-end', () => {
spyOn(service, 'setSession');
spyOn(service, 'login').and.callThrough();
let result: any;
service.login(accountDetails.UserName, accountDetails.Password)
.subscribe((response) => {
result = response;
expect(service.setSession).toHaveBeenCalled();
expect(service.setSession).toHaveBeenCalledWith(apiResponse);
expect(result).toEqual(apiResponse);
});
const request = controller.expectOne(AppConfig.apiEndPoint);
request.flush(apiResponse);
});
});
我错过了一些关键要素:
request.flush
并测试请求我还稍微更改了登录组件及其在没有订阅的情况下对服务的调用。 相反,该服务在成功响应时调用setSession
。 我已经编辑了问题。 再次感谢@AliF50提供的宝贵非官方资源~!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.