Jasmine spyOn 在第一次测试执行后调用真正的函数



第一个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(() => {
    ....
  }));
});

最新更新