Как варьировать шпионские результаты между тестами - PullRequest
0 голосов
/ 18 марта 2020

Я пишу несколько тестов для компонента Angular, который зависит от службы.

Эта служба имеет член stageData publi c, и я хочу проверить, работает ли компонент правильно, в зависимости от содержимого stageData.

Так как мне нужно издеваться над сервисом, я создал шпиона и определил, что он будет возвращать для stageData, но я не могу изменить это в каждом тесте.

describe('ProgressComponent', () => {
  let component: ProgressComponent;
  let fixture: ComponentFixture<ProgressComponent>;
  let progressStageService: any;
  const signStage = new StageCompletionModel();
  const inkStage = new StageCompletionModel();

  beforeEach(async(() => {
    signStage.stage = Stage.Sign;
    inkStage.stage = Stage.Ink;

    progressStageService = jasmine.createSpyObj('ProgressStageService', ['getStageProgress']);
    progressStageService.stageData = [signStage];

    TestBed.configureTestingModule({
      declarations: [ ProgressComponent ],
      providers: [ { provide: ProgressStageService, useValue: progressStageService } ],
      schemas: [ NO_ERRORS_SCHEMA ],
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(ProgressComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should not display Ink stage when it is not in stageData', () => {
    const callToAction: HTMLElement = fixture.nativeElement;
    const stageLabels = callToAction.querySelectorAll('span.stage-label');
    expect(Array.from(stageLabels).some(sl => sl.textContent.includes('Ink'))).toBeFalsy();
  });

  it('should display Ink stage when it is in stageData', () => {
    const callToAction: HTMLElement = fixture.nativeElement;
    const stageLabels = callToAction.querySelectorAll('span.stage-label');

    progressStageService.stageData = [signStage, inkStage];
    fixture.detectChanges();

    expect(Array.from(stageLabels).some(sl => sl.textContent.includes('Ink'))).toBeTruthy();
  });
});

Я пробовал много вариантов во втором тестовом примере, но stageData всегда содержит данные, которые он настроил в beforeEach.

1 Ответ

1 голос
/ 18 марта 2020

Таким образом, вы должны разбить его между более describes при издевательстве над данными. Первый fixture.detectChanges во втором beforeEach - это то, что «связывает» компонент и вызывает ngOnInit.

Попробуйте:

describe('ProgressComponent', () => {
  let component: ProgressComponent;
  let fixture: ComponentFixture<ProgressComponent>;
  let progressStageService: any;
  const signStage = new StageCompletionModel();
  const inkStage = new StageCompletionModel();

  beforeEach(async(() => {
    signStage.stage = Stage.Sign;
    inkStage.stage = Stage.Ink;

    progressStageService = jasmine.createSpyObj('ProgressStageService', ['getStageProgress']);

    TestBed.configureTestingModule({
      declarations: [ ProgressComponent ],
      providers: [ { provide: ProgressStageService, useValue: progressStageService } ],
      schemas: [ NO_ERRORS_SCHEMA ],
    })
    .compileComponents();
  }));

  beforeEach(() => {
    console.log('getting a handle on the fixture');
    fixture = TestBed.createComponent(ProgressComponent);
    console.log(fixture);
    component = fixture.componentInstance;
    // re-assign progressStageService to what was injected in the configureTestingModule
    // If you're using Angular 9, this should be .inject and not .get
    progressStageService = TestBed.get(ProgressStageService);
    // fixture.detectChanges(); => Remove fixture.detectChanges here
  });

 describe('stageData is [signStage]', () => {
   beforeEach(() => {
      // assign stageData to the service that was injected
      progressStageService.stageData = [signStage];
      fixture.detectChanges();
   });

  it('should not display Ink stage when it is not in stageData', () => {
    const callToAction: HTMLElement = fixture.nativeElement;
    const stageLabels = callToAction.querySelectorAll('span.stage-label');
    expect(Array.from(stageLabels).some(sl => sl.textContent.includes('Ink'))).toBeFalsy();
  });
 });

 describe('stageData is [signStage, inkStage]', () => {
   beforeEach(() => {
      // assign stageData to the service that was injected
      progressStageService.stageData = [signStage, inkStage];
      fixture.detectChanges();
   });

   it('should display Ink stage when it is in stageData', () => {
    const callToAction: HTMLElement = fixture.nativeElement;
    const stageLabels = callToAction.querySelectorAll('span.stage-label');
    expect(Array.from(stageLabels).some(sl => 
sl.textContent.includes('Ink'))).toBeTruthy();
  });
 });
});

...