NgRx 存储选择器单元测试
NgRx store selector unit testing
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);
});
});
但没有任何结果。
提前致谢!
您在设置模拟值之前调用 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);
});
});
未覆盖的行:
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);
});
});
但没有任何结果。
提前致谢!
您在设置模拟值之前调用 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);
});
});
未覆盖的行: