第一个it
测试有效,但第二个测试失败,抛出错误Cannot read property 'get' of undefined
,因为第二个测试调用具有在测试期间未定义的私有属性http
的真实服务
let expectedZipCode: string;
let activatedRoute: ActivatedRouteStub = new ActivatedRouteStub();
let fixture: ComponentFixture<WeatherComponent>;
let comp: WeatherComponent;
let weatherTile: HTMLElement;
let forecastGrid: HTMLElement;
let weatherService: WeatherUndergroundService;
let currentCondition: BehaviorSubject<any> = new BehaviorSubject<any>({});
describe('WeatherComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
providers: [
{ provide: ActivatedRoute, useValue: activatedRoute },
{ provide: WeatherUndergroundService },
{ provide: Http }
],
declarations: [
WeatherComponent
]
})
.compileComponents()
}));
beforeEach(()=> {
fixture = TestBed.createComponent(WeatherComponent);
comp = fixture.componentInstance;
weatherService = fixture.debugElement.injector.get(WeatherUndergroundService);
spyOn(weatherService, 'getCurrentConditions')
.and.returnValue(currentCondition);
spyOn(weatherService, 'getThreeDayForecast')
.and.returnValue(new BehaviorSubject<any>([]));
});
describe('when navigating to a valid zip code', () => {
beforeEach(() => {
expectedZipCode = '23441';
currentCondition.next({ location: 'Tasley, VA' });
activatedRoute.testParamMap = { zipCode: expectedZipCode };
});
//this works
it('should display the zip code city', fakeAsync(() => {
fixture.detectChanges();
tick();
fixture.detectChanges();
weatherTile = fixture.debugElement.query(By.css('.weather-tile')).nativeElement;
expect(weatherTile.querySelector('h3').textContent).toBe(currentCondition.getValue().location);
expect(comp.zipCode).toEqual(expectedZipCode);
}));
});
describe('when navigating without a zip code', () => {
beforeEach(() => {
expectedZipCode = '10028';
currentCondition.next({ location: 'New York, NY' });
activatedRoute.testParamMap = { zipCode: expectedZipCode };
});
//this fails
it('should display default to New York city', fakeAsync(() => {
fixture.detectChanges();
tick();
fixture.detectChanges();
weatherTile = fixture.debugElement.query(By.css('.weather-tile')).nativeElement;
expect(weatherTile.querySelector('h3').textContent).toBe(currentCondition.getValue().location);
expect(comp.zipCode).toEqual(expectedZipCode);
}));
});
});
我能够通过将ActivatedRouteStub
实例化移动到内部来解决此问题beforeEach()
如下所示。 对于好奇的人来说,ActivatedRouteStub
取自此页面上angular.io的示例。
...
//imports
let activatedRoute: ActivatedRouteStub;
let fixture: ComponentFixture<WeatherComponent>;
let comp: WeatherComponent;
let weatherTile: HTMLElement;
let forecastGrid: HTMLElement;
let weatherService: WeatherUndergroundService;
let currentCondition: BehaviorSubject<any> = new BehaviorSubject<any>({});
describe('WeatherComponent', () => {
beforeEach(async(() => {
activatedRoute = new ActivatedRouteStub();
TestBed.configureTestingModule({
providers: [
{ provide: ActivatedRoute, useValue: activatedRoute },
{ provide: WeatherUndergroundService },
{ provide: Http }
],
declarations: [
WeatherComponent
]
})
.compileComponents()
}));
beforeEach(()=> {
....
});
it('should display the zip code city given a valid zip code', fakeAsync(() => {
....
}));
it('should default to New York city without a zip code', fakeAsync(() => {
....
}));
});