我有一个nrwl / nx工作区,其中有一个名为missions-shared
的库,该库具有功能状态,在键missions
下,我还有一个称为BackendServiceClient
的后端服务。 此后端返回承诺(由于代码生成)
我的问题是后端返回了promises,而茉莉花大理石无法识别:
我正在尝试模拟后端。我为此使用测试提供程序
let backend = {
get: () => Promise.resolve({items: []})
}
TestBed.configureTestingModule({
...
providers : [{
provide: BackendServiceClient, useValue: backend
}]
...
这是MissionsEffect:
@Injectable()
export class MissionsEffects {
@Effect() loadMissions$ = this.dataPersistence.fetch(
MissionsActionTypes.LoadMissions,
{
run: (action: LoadMissions, state: MissionsPartialState) => {
return from(this.backend.get(new GetMissions())).pipe(
map(r => new MissionsLoaded(r.items))
);
},
onError: (action: LoadMissions, error) => {
console.error('Error', error);
return new MissionsLoadError(error);
}
}
);
constructor(
private dataPersistence: DataPersistence<MissionsPartialState>,
private backend: BackendClientService
) {}
}
然后我尝试使用茉莉花大理石测试这些@Effect
actions = hot('-a-|', { a: new LoadMissions() });
expect(effects.loadMissions$).toBeObservable(
hot('-a-|', { a: new MissionsLoaded([]) })
);
但是我在测试中遇到此错误:
● MissionsEffects › loadMissions$ › should work
expect(received).toEqual(expected) // deep equality
- Expected
+ Received
- Array [
- Object {
- "frame": 10,
- "notification": Notification {
- "error": undefined,
- "hasValue": true,
- "kind": "N",
- "value": MissionsLoaded {
- "payload": Array [],
- "type": "[Missions] Missions Loaded",
- },
- },
- },
- Object {
- "frame": 30,
- "notification": Notification {
- "error": undefined,
- "hasValue": false,
- "kind": "C",
- "value": undefined,
- },
- },
- ]
+ Array []
似乎是因为我正在使用Promise(应有的方式)来模拟后端,所以它无法识别返回的Observable。
如果我将模拟更改为:
let backend = {
get: () => of({items: []})
}
然后测试成功。
这是测试:
describe('MissionsEffects', () => {
let actions: Observable<any>;
let effects: MissionsEffects;
let backend = {
get: () => of({items: []})
}
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
NxModule.forRoot(),
StoreModule.forRoot({}),
EffectsModule.forRoot([]),
RouterModule.forRoot([])
],
providers: [
MissionsEffects,
DataPersistence,
provideMockActions(() => actions),
{ provide: APP_BASE_HREF, useValue: '/' },
{ provide: BackendClientService, useValue: backend }
]
});
effects = TestBed.get(MissionsEffects);
});
describe('loadMissions$', () => {
it('should work', () => {
actions = hot('-a-|', { a: new LoadMissions() });
expect(effects.loadMissions$).toBeObservable(
hot('-a-|', { a: new MissionsLoaded([]) })
);
});
});
});
我可以确认问题不是由于使用@ nrwl / DataPersistence,因为以下@Effect会产生相同的错误:
@Injectable()
export class MissionsEffects {
@Effect() loadMissions$ = this.actions$
.pipe(
ofType(MissionsActionTypes.LoadMissions),
switchMap(loadMission => {
return from(this.backend.get(new GetMissions())
.then(r => new MissionsLoaded(r.items))
.catch(e => new MissionsLoadError(e)))
})
)
constructor(
private actions$: Actions,
private backend: BackendClientService
) {}
}
有人可以帮助我确切地了解这里的问题吗?为什么我不能使用嘲笑的诺言进行测试?
答案 0 :(得分:0)
您可以尝试将测试包装在async()
中,以确保所有异步调用均已完成。尽管resolve
是同步的,但是from
将添加一个.then
,并且仍将其等待解决为微任务。用it
或async
包装fakeAsync
函数可以解决此问题。