jasmine spyOn在第一次测试执行后调用实际函数

时间:2017-10-29 15:37:44

标签: angular jasmine angular-routing

第一个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);
    }));
  });
});

1 个答案:

答案 0 :(得分:0)

我能够通过在ActivatedRouteStub内移动beforeEach()实例来解决问题,如下所示。对于好奇的人来说,ActivatedRouteStub来自angular.io的example on this page

...
//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(() => {
    ....
  }));
});