【问题标题】:NgRx store selector unit testingNgRx 存储选择器单元测试
【发布时间】:2021-04-12 06:35:17
【问题描述】:
ngOnInit(): void {
        this.format = this.store.select(selectUserSettings).pipe(
          filter(
            (userSettings: UserSettingsState) =>
              Boolean(userSettings) && !userSettings.errors && !userSettings.isLoading && !!userSettings.localizationProfile
          ),
          map((userSettings: UserSettingsState) =>
            userSettings.localizationProfile.dateFormat.toLocaleLowerCase().replace('mm', 'MM')
          ),
          takeUntil(this.destroy)
        );
      }

如何为这个函数编写单元测试?我试图模拟像 mockUserSettingsSelector = store.overrideSelector(selectUserSettings, initialState.userSettings); 这样的选择器, 和测试

    describe('OverdueTableComponent', () => {
  let component: OverdueTableComponent;
  let fixture: ComponentFixture<OverdueTableComponent>;
  let store: MockStore;
  const initialState: SettingsState = new SettingsInitialState();
  let mockUserSettingsSelector: MemoizedSelector<SettingsState, UserSettingsState>;

  beforeEach(
    waitForAsync(() => {
      TestBed.configureTestingModule({
        declarations: [OverdueTableComponent, OverdueEventTypeTranslationComponent],
        imports: [SimplebarAngularModule, StoreModule.forRoot({}), StoreModule.forFeature('settings', settingsReducer)],
        providers: [OverdueTableComponent, OverdueEventTypeTranslationComponent, provideMockStore({ initialState })],
      }).compileComponents();
    })
  );

  beforeEach(() => {
    fixture = TestBed.createComponent(OverdueTableComponent);
    component = fixture.componentInstance;
    store = TestBed.inject(MockStore);
    mockUserSettingsSelector = store.overrideSelector(selectUserSettings, initialState.userSettings);
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  it('format should not be null', () => {
    mockUserSettingsSelector.setResult({
      errors: undefined,
      isLoading: false,
      localizationProfile: {
        currency: 'dummy-currency',
        currencySymbol: 'dummy-currency-symbol',
        dateFormat: 'dd/MM/yyyy',
        language: 'English (British)',
        timezone: 'dummy-timezone',
      },
      successfullyUpdated: false,
    });
    store.refreshState();
    fixture.detectChanges();
    component.ngOnInit();
    expect(component.format).not.toBe(null);
  });
});

但没有任何结果。

提前致谢!

【问题讨论】:

    标签: angular unit-testing selector ngrx store


    【解决方案1】:

    您在设置模拟值之前调用component.ngOnInit(),因此不会设置它。

    请注意,第一个fixture.detectChanges() 也会触发ngOnInit 方法。如果在 beforeEach 中调用它,则需要在设置完成后将其从那里移除并放置在测试用例中(并且您可以移除 ngOnInit 的显式触发器)


    编辑:

    describe('OverdueTableComponent', () => {
      ...
    
      beforeEach(
        waitForAsync(() => {
          ...
        })
      );
    
      beforeEach(() => {
        fixture = TestBed.createComponent(OverdueTableComponent);
        component = fixture.componentInstance;
        store = TestBed.inject(MockStore);
        mockUserSettingsSelector = store.overrideSelector(selectUserSettings, initialState.userSettings);
        // PLEASE REMOVE THIS LINE fixture.detectChanges();
      });
    
      it('should create', () => {
        fixture.detectChanges(); // ADD THE CHANGE DETECTION HERE
        expect(component).toBeTruthy();
      });
    
      it('format should not be null', () => {
        mockUserSettingsSelector.setResult({
          errors: undefined,
          isLoading: false,
          localizationProfile: {
            currency: 'dummy-currency',
            currencySymbol: 'dummy-currency-symbol',
            dateFormat: 'dd/MM/yyyy',
            language: 'English (British)',
            timezone: 'dummy-timezone',
          },
          successfullyUpdated: false,
        });
        store.refreshState();
        fixture.detectChanges();
        // REMOVE THIS LINE as fixture.detectChanges() does it for you 
        // component.ngOnInit();
        expect(component.format).not.toBe(null);
      });
    });
    

    未发现的行:

    【讨论】:

    • 我在fixture.detectChanges()之后移动了component.ngOnInit(),但仍然无法正常工作
    • 请提供更多关于您的测试的信息,尤其是测试设置。 store.refreshState 也是异步操作吗?
    • 正如我在回答中所写,您需要从 beforeEach 中删除 fixture.detectChanges。测试中的第一个 fixture.detectChanges 调用会触发组件中的 onInit 方法。
    • 这也意味着您需要将其添加到每个 it 块中(在第一个测试“应该创建”作为第一行,并在模拟存储之后的测试中)
    • 我这样做了,但仍有未覆盖的线条。我编辑了问题并上传了一张图片。
    猜你喜欢
    • 2019-09-08
    • 1970-01-01
    • 1970-01-01
    • 2022-06-14
    • 1970-01-01
    • 1970-01-01
    • 2021-09-29
    • 2021-11-29
    • 1970-01-01
    相关资源
    最近更新 更多