测试服务 Angular
Testing Service Angular
我面临一个问题,我不知道如何解决它,因为我对前面的测试很陌生。
现在我正在测试具有此代码的服务:
import { Injectable } from '@angular/core';
import { EndpointLocatorService } from './endpointLocator.service';
import { Http, Headers } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
@Injectable()
export class CancelAppService {
constructor(private readonly http: Http,
private readonly _endPointLocator: EndpointLocatorService) { }
getScopeSignature(signatureToken: string) {
const url = this._endPointLocator.locate('cancelApp');
const language = sessionStorage.getItem('languageSession');
const headers = new Headers({
'Content-Type': 'application/json',
'Accept-Language': language,
'X-B3-TraceId': sessionStorage.getItem('requestID')
});
const body = JSON.stringify({ 'signatureToken': signatureToken });
return this.http.post(url, body, { headers }).map(data => {
return data.json();
}).catch((error: any) => {
return Observable.throw(new Error(error.status));
});
}
}
测试文件包含:
import { TestBed } from '@angular/core/testing';
import { CancelAppService } from './cancelApp.service';
import { HttpModule } from '@angular/http';
import { EndpointLocatorService } from './endpointLocator.service';
import { AppConfig } from '../app.config';
import 'jasmine';
fdescribe('CancelAppService', () => {
let cancelService: CancelAppService; // Add this
let endLocator: EndpointLocatorService;
const mockData = {
"signature_token": "returnedToken"
};
const body = JSON.stringify({ 'signatureToken': 'givenToken' });
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
HttpModule
],
providers: [
CancelAppService,
AppConfig,
EndpointLocatorService
]
});
cancelService = TestBed.get(CancelAppService); // Add this
endLocator = TestBed.get(EndpointLocatorService);
});
it('should be created', () => { // Remove inject()
expect(cancelService).toBeDefined();
});
it('should call the service', () => {
spyOn(endLocator, 'locate').and.returnValue('someUrl');
spyOn(cancelService, 'getScopeSignature').and.callThrough();
cancelService.getScopeSignature(body);
expect(cancelService.getScopeSignature).toHaveBeenCalled();
});
it('should return a object', () => {
(done: DoneFn) => {
spyOn(endLocator, 'locate').and.returnValue('someUrl');
spyOn(cancelService, 'getScopeSignature').and.returnValue(mockData);
cancelService.getScopeSignature(body).subscribe(data => {
expect(data).toEqual(mockData);
done();
});
}
});
});
问题是,当我尝试测试返回的数据地图时,我看起来像是成功测试,但覆盖率说我没有覆盖地图的线条,并抓住了。
知道我做错了什么吗?以及如何解决?
非常感谢!!
您正在模拟正在测试的服务,您应该模拟您的服务正在使用的服务 EndpointLocatorService
,甚至可能 HttpClient
以尽量减少模拟。您可以通过单步执行代码来验证这一点。
让我在代码中解释为什么没有命中这些行。
// In this example, the lines are hit, but after the test exited.
it('should call the service', () => {
spyOn(endLocator, 'locate').and.returnValue('someUrl');
spyOn(cancelService, 'getScopeSignature').and.callThrough();
// Here you are calling a method yourself and checking that it was
// called, it doesn't make sense, this test should make sure
// You should check that your endLocator was called.
// Note that because you are not waiting for the promise to resolve,
// The test finishes before either callback is handled.
cancelService.getScopeSignature(body);
expect(cancelService.getScopeSignature).toHaveBeenCalled();
});
// In this example the lines in your test are never hit because you
// mocked it
it('should return a object', () => {
(done: DoneFn) => {
spyOn(endLocator, 'locate').and.returnValue('someUrl');
// Here you are mocking getScopeSignature completely so it doesn't
// Run any of your lines that you are trying to test
// It just tests that you mocked it correctly
spyOn(cancelService, 'getScopeSignature').and.returnValue(mockData);
cancelService.getScopeSignature(body).subscribe(data => {
expect(data).toEqual(mockData);
done();
});
}
});
我无法重写您的测试,所以它实际测试了它,因为它取决于 EndpointLocatorService
的工作方式,您也可以选择在该级别模拟它。我通常选择在 HttpClient
级别进行模拟,因为我可以从网络选项卡复制粘贴响应。
重点是您需要模拟服务使用的服务,而不是服务本身。您可以选择模拟组件使用的直接服务,也可以模拟更深层次的服务。例如,您的 EndpointLocatorService
可能需要调用 HttpClient
,您可以选择模拟任一服务。
参见 https://angular.io/guide/testing#httpclienttestingmodule and https://alligator.io/angular/testing-httpclient/
我面临一个问题,我不知道如何解决它,因为我对前面的测试很陌生。
现在我正在测试具有此代码的服务:
import { Injectable } from '@angular/core';
import { EndpointLocatorService } from './endpointLocator.service';
import { Http, Headers } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
@Injectable()
export class CancelAppService {
constructor(private readonly http: Http,
private readonly _endPointLocator: EndpointLocatorService) { }
getScopeSignature(signatureToken: string) {
const url = this._endPointLocator.locate('cancelApp');
const language = sessionStorage.getItem('languageSession');
const headers = new Headers({
'Content-Type': 'application/json',
'Accept-Language': language,
'X-B3-TraceId': sessionStorage.getItem('requestID')
});
const body = JSON.stringify({ 'signatureToken': signatureToken });
return this.http.post(url, body, { headers }).map(data => {
return data.json();
}).catch((error: any) => {
return Observable.throw(new Error(error.status));
});
}
}
测试文件包含:
import { TestBed } from '@angular/core/testing';
import { CancelAppService } from './cancelApp.service';
import { HttpModule } from '@angular/http';
import { EndpointLocatorService } from './endpointLocator.service';
import { AppConfig } from '../app.config';
import 'jasmine';
fdescribe('CancelAppService', () => {
let cancelService: CancelAppService; // Add this
let endLocator: EndpointLocatorService;
const mockData = {
"signature_token": "returnedToken"
};
const body = JSON.stringify({ 'signatureToken': 'givenToken' });
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
HttpModule
],
providers: [
CancelAppService,
AppConfig,
EndpointLocatorService
]
});
cancelService = TestBed.get(CancelAppService); // Add this
endLocator = TestBed.get(EndpointLocatorService);
});
it('should be created', () => { // Remove inject()
expect(cancelService).toBeDefined();
});
it('should call the service', () => {
spyOn(endLocator, 'locate').and.returnValue('someUrl');
spyOn(cancelService, 'getScopeSignature').and.callThrough();
cancelService.getScopeSignature(body);
expect(cancelService.getScopeSignature).toHaveBeenCalled();
});
it('should return a object', () => {
(done: DoneFn) => {
spyOn(endLocator, 'locate').and.returnValue('someUrl');
spyOn(cancelService, 'getScopeSignature').and.returnValue(mockData);
cancelService.getScopeSignature(body).subscribe(data => {
expect(data).toEqual(mockData);
done();
});
}
});
});
问题是,当我尝试测试返回的数据地图时,我看起来像是成功测试,但覆盖率说我没有覆盖地图的线条,并抓住了。
知道我做错了什么吗?以及如何解决?
非常感谢!!
您正在模拟正在测试的服务,您应该模拟您的服务正在使用的服务 EndpointLocatorService
,甚至可能 HttpClient
以尽量减少模拟。您可以通过单步执行代码来验证这一点。
让我在代码中解释为什么没有命中这些行。
// In this example, the lines are hit, but after the test exited.
it('should call the service', () => {
spyOn(endLocator, 'locate').and.returnValue('someUrl');
spyOn(cancelService, 'getScopeSignature').and.callThrough();
// Here you are calling a method yourself and checking that it was
// called, it doesn't make sense, this test should make sure
// You should check that your endLocator was called.
// Note that because you are not waiting for the promise to resolve,
// The test finishes before either callback is handled.
cancelService.getScopeSignature(body);
expect(cancelService.getScopeSignature).toHaveBeenCalled();
});
// In this example the lines in your test are never hit because you
// mocked it
it('should return a object', () => {
(done: DoneFn) => {
spyOn(endLocator, 'locate').and.returnValue('someUrl');
// Here you are mocking getScopeSignature completely so it doesn't
// Run any of your lines that you are trying to test
// It just tests that you mocked it correctly
spyOn(cancelService, 'getScopeSignature').and.returnValue(mockData);
cancelService.getScopeSignature(body).subscribe(data => {
expect(data).toEqual(mockData);
done();
});
}
});
我无法重写您的测试,所以它实际测试了它,因为它取决于 EndpointLocatorService
的工作方式,您也可以选择在该级别模拟它。我通常选择在 HttpClient
级别进行模拟,因为我可以从网络选项卡复制粘贴响应。
重点是您需要模拟服务使用的服务,而不是服务本身。您可以选择模拟组件使用的直接服务,也可以模拟更深层次的服务。例如,您的 EndpointLocatorService
可能需要调用 HttpClient
,您可以选择模拟任一服务。
参见 https://angular.io/guide/testing#httpclienttestingmodule and https://alligator.io/angular/testing-httpclient/