我有一个在构造器中定义我的休息点的服务,因此我将其设置为变量。当我运行单元测试时,这些属性将返回未定义状态。我是单元测试的新手,所以不确定是否错过了明显的步骤...
这是我的服务。
import { HttpClient, HttpErrorResponse, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { Observable } from 'rxjs/Observable';
@Injectable()
export class PulldownService {
public pulldownData: any = [];
public restURL;
constructor(public http: HttpClient, public router: Router) {
this.getEnvConf().subscribe(
res => {
this.restURL = res[window.location.hostname];
}
);
}
getEnvConf(): Observable<any> {
return this.http.get('./assets/data/environment-config.json');
}
postClaim() {
let headerTarget;
if (this.restURL['target_env']) {
headerTarget = {'Accept': 'application/json', 'Content-Type': 'application/json', 'target_env': this.restURL['targetEnv']};
} else {
headerTarget = {'Accept': 'application/json', 'Content-Type': 'application/json'};
}
const httpHeaders = new HttpHeaders(headerTarget);
const options = { headers: httpHeaders };
return this.http.post( this.restURL['restEndPoint'],
{ 'names' : [
'PersonRelationType',
'State',
...
...
]}, options ).subscribe(
data => {
// Success!
this.pulldownData.push(data);
}
,
(err: HttpErrorResponse) => {
if (err.error instanceof Error) {
// A client-side or network error occurred.
this.router.navigateByUrl('/error');
console.log('An error occurred:', err.error.message);
} else {
// The backend returned an unsuccessful response code.
this.router.navigateByUrl('/error');
console.log(`Backend returned code ${err.status}, body was: ${err.error}`);
}
},
() => {
this.router.navigateByUrl('/getstart');
}
);
}
}
这是我的服务。spec.ts
import { PulldownService } from './pulldown.service';
import { TestBed } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { HttpRequest } from '@angular/common/http';
describe('PulldownService', () => {
let service: PulldownService;
let httpTestingController: HttpTestingController;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ HttpClientTestingModule, RouterTestingModule ],
providers: [ PulldownService ]
});
httpTestingController = TestBed.get(HttpTestingController);
service = TestBed.get(PulldownService);
});
describe('getEnvConfig', () => {
it('should call get with the correct url', () => {
// no subscribe method called in getEnvConfig
// service.getEnvConf().subscribe();
const req = httpTestingController.expectOne('./assets/data/environment-config.json');
req.flush({ 'restEndPoint': 'http://localhost:8080/typelist?version=1', 'target_env': null});
httpTestingController.verify();
// expect(req.request.url.endsWith('environment-config.json')).toEqual(true);
});
});
describe('postClaim', () => {
it('should be called with proper arguments', () => {
const responseForm = '<form />';
const pulldownService = TestBed.get(PulldownService);
const http = TestBed.get(HttpTestingController);
let postResponse;
pulldownService.postClaim().subscribe((response) => {
postResponse = response;
});
http.expectOne((request: HttpRequest<any>) => {
return request.method === 'POST'
&& request.url === 'http://localhost:8080/typelist?version=1'
&& JSON.stringify(request.body) === JSON.stringify({
names: ['State']
})
&& request.headers.get('Accept') === 'application/json'
&& request.headers.get('Content-Type') === 'application/json'
&& request.headers.get('target_env') === null;
}).flush(responseForm);
expect(postResponse).toEqual(responseForm);
});
});
})
我一直收到的错误是:TypeError:无法读取未定义的属性'target_env'。从函数中删除“ target_env”后,我看到了一个新的“ restEndPoint”错误。
在此方面的任何帮助将不胜感激。谢谢
答案 0 :(得分:0)
您的postClaim()
方法需要定义restURL
。 restURL
仅在服务收到构造函数中发送的请求响应时定义。
但是在第二个单元测试中,您永远不会告诉http测试控制器在调用postClaim()
之前刷新对此第一个请求的任何响应。因此restURL
是未定义的,因此是错误。
即使您修复了测试,您的服务也处于竞争状态:如果提早调用,则postClaim()方法将具有与测试中相同的错误。为什么不使用environments support of the CLI来定义静态的,预先已知的配置选项?
答案 1 :(得分:0)
target_env和restEndPoint的错误是因为this.restURL
未定义。在您的第一个单元测试中,您已经正确模拟了调用,但是您应该返回{ 'localhost' : { 'restEndPoint': 'http://localhost:8080/typelist?version=1', 'target_env': null } }
,因为在PulldownService的构造函数中,您正在设置this.restURL = res[window.location.hostname]
(而不是this.restURL = res
) 。在第二个单元测试中,您根本没有嘲笑初始获取。
由于您的所有单元测试都可能需要此处理,因此建议在beforeEach()
之后将模拟调用移至service = TestBed.get(PulldownService);
旁注:由于已经有了pulldownService
和http
,因此在第二次测试中无需再次定义httpTestingController
和service
。