根据测试执行顺序,使用TestBed.inject进行角单元测试成功/失败

弗朗切斯科

我有一个使用Jest for UnitTests的角度应用程序(v11.1.0)。

TestBed.inject为了在单个测试中获取服务实例而使用spyOn对其方法进行测试,或者它们已被调用或模拟返回值。

但是,切换到Typescriptstrict模式后,测试失败。但是,如果我更改某些测试的顺序,则一切运行都会很顺利。看来,模拟服务仍在不同的单元测试之间进行交互。

我尝试使用jest.resetAllMocks(),但它也不能解决问题。在我使用的代码下面:

单元测试

describe('AppComponent', () => {
  let component: AppComponent;
  let fixture: ComponentFixture<AppComponent>;

  beforeEach(
    waitForAsync(() => {
      TestBed.configureTestingModule({
        imports: [
          RouterTestingModule,
          HttpClientTestingModule,
          TranslateModule.forRoot(),
        ],
        declarations: [AppComponent],
        providers: [
          { provide: InformationService, useValue: informationServiceMock }
        ],
      }).compileComponents();
    })
  );

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

 describe('Test set', () => {
    it(`should have default text`, () => {
      fixture.detectChanges();
      expect(component.maintenanceBannerMessage).toBe('BANNER DE');
      expect(component.maintenanceBannerTitle).toBe('TITLE DE');
    });

    it(`Should open function`, () => {
      const dialog = TestBed.inject(MatDialog);
      const informationService = TestBed.inject(InformationService);
      jest.spyOn(informationService, 'updateOverlayAction');
      jest.spyOn(dialog, 'open');
      fixture.detectChanges();

      expect(dialog.open).toHaveBeenCalled();
      expect(informationService.updateOverlayAction).toHaveBeenCalled();
    });

    //------------------------------------------------------------
    // If I move this test in 2. position, the test `Should open function` FAILS
    // as getAnnouncementsByType keeps returning null instead of getting it from the
    // informationServiceMock provided in the configureTestingModule

    it(`should not be showed`, () => {
      const informationService = TestBed.inject(InformationService);
      jest
        .spyOn(informationService, 'getAnnouncementsByType')
        .mockReturnValue(of(null as any));
      fixture.detectChanges();

      expect(component.maintenanceBannerMessage).toBeUndefined();
      expect(component.maintenanceBannerTitle).toBeUndefined();
    });
    //------------------------------------------------------------

    it(`should not be showed`, () => {
      const dialog = TestBed.inject(MatDialog);
     const informationService = TestBed.inject(InformationService);
      jest
        .spyOn(informationService, 'getAnnouncementsByType')
        .mockReturnValue(of(null as any));
      jest.spyOn(dialog, 'open');
      fixture.detectChanges();

      expect(dialog.open).not.toHaveBeenCalled();
    });
  });
});

服务模拟

export const announcementsMockData = [
  {
    announcementId: '6000',
    type: AnnouncementType.BANNER,
    text: { de: 'BANNER DE', fr: 'BANNER FR', it: 'BANNER IT', en: 'BANNER EN' },
    title: { de: 'TITLE DE', fr: 'TITLE FR', it: 'TITLE IT', en: 'TITLE EN' }
  }, {
    announcementId: '6100',
    type: AnnouncementType.OVERLAY,
    text: { de: 'OVERLAY DE', fr: 'OVERLAY FR', it: 'OVERLAY IT', en: 'OVERLAY EN' },
    title: { de: 'OVERLAY DE', fr: 'OVERLAY FR', it: 'OVERLAY IT', en: 'OVERLAY EN' },
    _links: { create: { href: '/announcements/6100/actions' } }
  }
];

export const informationServiceMock = {
  getAnnouncementsByType: (type: AnnouncementType) => {
    return announcementsMockData.map(a => new Announcement(a)).filter(a => a.type === type);
  },
  updateOverlayAction: (link: ResourceLink, action: OverlayAction) => of(null),
};

应用程序组件

this.informationService.getAnnouncementsByType(AnnouncementType.BANNER)
  .pipe(takeUntil(this.destroy$))
  .subscribe(([currentLanguage, banners]) => {
    if (banners?.length > 0) {
      if (banners[0].title) {
        this.maintenanceBannerTitle = banners[0].title[currentLanguage.key as keyof LanguageObject];
      }
      if (banners[0].text) {
        this.maintenanceBannerMessage =
          banners[0].text[currentLanguage.key as keyof LanguageObject];
      }
    }
  });
那将是烧瓶

应将特定于测试的间谍还原到所有测试都通用的某种实现方式,否则这样做会导致测试交叉污染,因为测试会影响后续测试。

jest.resetAllMocks()提供不良行为,应完全避免。在中使用时beforeEach,它将毫无例外地重置所有间谍程序的实现,并使它们成为存根。当用于测试时,这也会导致测试交叉污染。如果需要重置特定的间谍实施,可以使用来完成mockReset()

根据经验,jest.restoreAllMocks()应该在中使用beforeEach它,以将创建的所有间谍恢复jest.spyOn到原始实现(如果有)。对于所有测试,通常都需要此行为,因此可以在Jest配置中启用它。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

根据测试执行顺序,使用TestBed.inject进行角单元测试成功/失败

来自分类Dev

在SonarQube中无法获得单元测试成功

来自分类Dev

多个文件删除方法的单元测试成功

来自分类Dev

Python单元测试成功断言None为False

来自分类Dev

(PHP项目)(单元测试成功)(未显示)

来自分类Dev

SonarQube中的Scala项目单元测试成功

来自分类Dev

没有声纳报告单元测试成功

来自分类Dev

Chai + mocha, 测试成功,拒绝失败

来自分类Dev

单元测试失败

来自分类Dev

Sonarqube上未显示单元测试范围-通过Jenkins Sonar插件运行-测试成功显示正确

来自分类Dev

Sonarqube上未显示单元测试范围-通过Jenkins Sonar插件运行-测试成功显示正确

来自分类Dev

为什么我在SonarQube中看不到“单元测试覆盖率”小部件的“单元测试成功”部分

来自分类Dev

如何对MatDialog(角材料)进行单元测试的正确方法?

来自分类Dev

角单元测试求和

来自分类Dev

角单元测试求和

来自分类Dev

使用Google测试进行单元测试

来自分类Dev

NUnit:如何对另一个单元测试失败进行单元测试?

来自分类Dev

使用实体框架进行单元测试的单元测试

来自分类Dev

使用Arquillian TestRunner TestNG顺序执行测试

来自分类Dev

断言失败后如何继续进行单元测试?

来自分类Dev

如何对失败的文件删除进行单元测试?

来自分类Dev

角单元测试与集成测试

来自分类Dev

尽管测试成功,表单身份验证仍失败

来自分类Dev

Umbraco单元测试失败

来自分类Dev

验证单元测试失败

来自分类Dev

“单元测试失败”的BeautifulSoup

来自分类Dev

Umbraco单元测试失败

来自分类Dev

Rails单元测试失败

来自分类Dev

单元测试未执行时,鼻子测试失败

Related 相关文章

热门标签

归档