Angular NgRx 集成测试不工作(使用 Nx 和 Jest)
Angular NgRx integration test not working (with Nx and Jest)
我有一个在幕后使用 NgRx 的外观 class。当我在我的应用程序中使用它时,外观本身正在工作,但通过集成测试它不起作用(更好的说法是:测试不起作用)。我正在使用 Nx(不要认为那很重要)和 Jest。
注意:对于集成测试,我的意思是我不想模拟 NgRx 部分,我也想测试 NgRx 逻辑。只有数据服务被模拟。
外观class非常简单。这是它的摘录:
@Injectable({
providedIn: 'root'
})
export class ProfileFacade {
public isProfileLoaded$ = this.store.select(Selectors.isProfileLoaded);
public constructor(private store: Store<fromProfile.PartialState>) {
/* */
}
public loadProfile(): void {
this.dispatch(Actions.loadProfile());
}
private dispatch(action: Action): void {
this.store.dispatch(action);
}
}
dipatched loadProfile 操作触发的效果是 returns ProfileLoadSucceeded 操作包含通过 ProfileService 获取的数据。然后,reducer 捕获此操作,将配置文件数据放入存储中,并将 isProfileLoaded 属性 设置为 true。
这是我的集成测试设置:
describe('ProfileFacade integration', () => {
let facade: ProfileFacade;
let store: Store<fromProfile.PartialState>;
let profileServiceSpy: SpyObject<ProfileService>;
beforeEach(() => {
@NgModule({
imports: [
StoreModule.forFeature(fromProfile.PROFILE_FEATURE_KEY, fromProfile.reducer),
EffectsModule.forFeature([ProfileEffects])
],
providers: [
ProfileFacade,
mockProvider(ProfileService),
]
})
class CustomFeatureModule {}
@NgModule({
imports: [NxModule.forRoot(), StoreModule.forRoot({}), EffectsModule.forRoot([]), CustomFeatureModule]
})
class RootModule {}
TestBed.configureTestingModule({ imports: [RootModule] });
store = TestBed.inject(Store);
facade = TestBed.inject(ProfileFacade);
profileServiceSpy = TestBed.inject(ProfileService) as SpyObject<ProfileService>;
});
...
});
以下是我在集成测试中尝试过的许多事情的精选:
用 expect(...).toBeObservable(...)
it(`should set isProfileLoaded to true`, () => {
profileServiceSpy.get.and.returnValue(hot('^x|', { x: profile })); // I've tried several variations of hot and cold
facade.loadProfile();
const expected = cold('--b', { b: true });
expect(facade.isProfileLoaded$).toBeObservable(expected);
});
使用 toPromise() 和 then()
it(`should set isProfileLoaded to true`, () => {
// same 2 lines as in 1)
return facade.isProfileLoaded$.toPromise().then(result => expect(result).toBe(true));
});
用 expect(...toPromise()).resolves()
it(`should set isProfileLoaded to true`, () => {
// same 2 lines as in 1)
return expect(facade.isProfileLoaded$.toPromise()).resolves.toBe(true);
});
订阅并完成()
it(`should set isProfileLoaded to true`, done => {
// same 2 lines as in 1)
facade.isProfileLoaded$.subscribe(result => {
expect(result).toBe(true);
done();
});
});
我只是展示了 isProfileLoaded 的测试,但我对数据本身的测试也有同样的问题。结果值始终为 false 或 null:门面的选择器结果似乎没有反映商店的内容。
虽然商店本身似乎运作良好。通过在不同的地方添加 console.log 语句,我可以看到来自模拟服务的数据正在按预期流动。它存在于 effect、reducer 和结果状态中。
我想我遗漏了一些明显的东西,但是什么?我还没有找到使用这种技术组合执行这种集成测试的示例。
由于您已经在使用 Nx,我能想到的一种方法是:
import { readFirst } from '@nrwl/nx/testing';
it(`should set isProfileLoaded to true`, async (done) => {
try {
profileServiceSpy.get.and.returnValue(of(profile));
facade.loadProfile();
const isProfileLoaded = await readFirst(facade.isProfileLoaded$);
expect(isProfileLoaded).toBeTruthy();
done();
} catch (error) {
done.fail(error);
}
});
我有一个在幕后使用 NgRx 的外观 class。当我在我的应用程序中使用它时,外观本身正在工作,但通过集成测试它不起作用(更好的说法是:测试不起作用)。我正在使用 Nx(不要认为那很重要)和 Jest。
注意:对于集成测试,我的意思是我不想模拟 NgRx 部分,我也想测试 NgRx 逻辑。只有数据服务被模拟。
外观class非常简单。这是它的摘录:
@Injectable({
providedIn: 'root'
})
export class ProfileFacade {
public isProfileLoaded$ = this.store.select(Selectors.isProfileLoaded);
public constructor(private store: Store<fromProfile.PartialState>) {
/* */
}
public loadProfile(): void {
this.dispatch(Actions.loadProfile());
}
private dispatch(action: Action): void {
this.store.dispatch(action);
}
}
dipatched loadProfile 操作触发的效果是 returns ProfileLoadSucceeded 操作包含通过 ProfileService 获取的数据。然后,reducer 捕获此操作,将配置文件数据放入存储中,并将 isProfileLoaded 属性 设置为 true。
这是我的集成测试设置:
describe('ProfileFacade integration', () => {
let facade: ProfileFacade;
let store: Store<fromProfile.PartialState>;
let profileServiceSpy: SpyObject<ProfileService>;
beforeEach(() => {
@NgModule({
imports: [
StoreModule.forFeature(fromProfile.PROFILE_FEATURE_KEY, fromProfile.reducer),
EffectsModule.forFeature([ProfileEffects])
],
providers: [
ProfileFacade,
mockProvider(ProfileService),
]
})
class CustomFeatureModule {}
@NgModule({
imports: [NxModule.forRoot(), StoreModule.forRoot({}), EffectsModule.forRoot([]), CustomFeatureModule]
})
class RootModule {}
TestBed.configureTestingModule({ imports: [RootModule] });
store = TestBed.inject(Store);
facade = TestBed.inject(ProfileFacade);
profileServiceSpy = TestBed.inject(ProfileService) as SpyObject<ProfileService>;
});
...
});
以下是我在集成测试中尝试过的许多事情的精选:
用 expect(...).toBeObservable(...)
it(`should set isProfileLoaded to true`, () => { profileServiceSpy.get.and.returnValue(hot('^x|', { x: profile })); // I've tried several variations of hot and cold facade.loadProfile(); const expected = cold('--b', { b: true }); expect(facade.isProfileLoaded$).toBeObservable(expected); });
使用 toPromise() 和 then()
it(`should set isProfileLoaded to true`, () => { // same 2 lines as in 1) return facade.isProfileLoaded$.toPromise().then(result => expect(result).toBe(true)); });
用 expect(...toPromise()).resolves()
it(`should set isProfileLoaded to true`, () => { // same 2 lines as in 1) return expect(facade.isProfileLoaded$.toPromise()).resolves.toBe(true); });
订阅并完成()
it(`should set isProfileLoaded to true`, done => { // same 2 lines as in 1) facade.isProfileLoaded$.subscribe(result => { expect(result).toBe(true); done(); }); });
我只是展示了 isProfileLoaded 的测试,但我对数据本身的测试也有同样的问题。结果值始终为 false 或 null:门面的选择器结果似乎没有反映商店的内容。
虽然商店本身似乎运作良好。通过在不同的地方添加 console.log 语句,我可以看到来自模拟服务的数据正在按预期流动。它存在于 effect、reducer 和结果状态中。
我想我遗漏了一些明显的东西,但是什么?我还没有找到使用这种技术组合执行这种集成测试的示例。
由于您已经在使用 Nx,我能想到的一种方法是:
import { readFirst } from '@nrwl/nx/testing';
it(`should set isProfileLoaded to true`, async (done) => {
try {
profileServiceSpy.get.and.returnValue(of(profile));
facade.loadProfile();
const isProfileLoaded = await readFirst(facade.isProfileLoaded$);
expect(isProfileLoaded).toBeTruthy();
done();
} catch (error) {
done.fail(error);
}
});