如何正确使用 jasmine-marbles 来测试 ofType 中的多个动作
How to properly use jasmine-marbles to test multiple actions in ofType
我有一个 Effect,每次它收到一个以上的动作时都会被调用 "kind"
myEffect.effect.ts
someEffect$ = createEffect(() =>
this.actions$.pipe(
ofType(fromActions.actionOne, fromActions.actionTwo),
exhaustMap(() => {
return this.myService.getSomeDataViaHTTP().pipe(
map((data) =>
fromActions.successAction({ payload: data})
),
catchError((err) =>
ObservableOf(fromActions.failAction({ payload: err }))
)
);
})
)
);
在我的测试中,我试图“模拟两个不同的动作,但我总是以错误告终,而如果我尝试一个动作,它就完美无缺
The Before Each part
describe('MyEffect', () => {
let actions$: Observable<Action>;
let effects: MyEffect;
let userServiceSpy: jasmine.SpyObj<MyService>;
const data = {
// Some data structure
};
beforeEach(() => {
const spy = jasmine.createSpyObj('MyService', [
'getSomeDataViaHTTP',
]);
TestBed.configureTestingModule({
providers: [
MyEffect,
provideMockActions(() => actions$),
{
provide: MyService,
useValue: spy,
},
],
});
effects = TestBed.get(MyEffect);
userServiceSpy = TestBed.get(MyService);
});
This works perfectly
it('should return successActionsuccessAction', () => {
const action = actionOne();
const outcome = successAction({ payload: data });
actions$ = hot('-a', { a: action });
const response = cold('-a|', { a: data });
userServiceSpy.getSomeDataViaHTTP.and.returnValue(response);
const expected = cold('--b', { b: outcome });
expect(effects.someEffect$).toBeObservable(expected);
});
This doesn't work
it('should return successAction', () => {
const actions = [actionOne(), actionTwo()];
const outcome = successAction({ payload: data });
actions$ = hot('-a-b', { a: actions[0], b: actions[1] });
const response = cold('-a-a', { a: data });
userServiceSpy.getSomeDataViaHTTP.and.returnValue(response);
const expected = cold('--b--b', { b: outcome });
expect(effects.someEffect$).toBeObservable(expected);
});
这段代码有两个问题。
- 提示getSomeDataViaHTTPreturns两个值。这是错误的,响应与您的第一个示例没有什么不同:'-a|'
- 它期望在 40 毫秒后出现第二个 successAction(--b--b,计算破折号的数量)。这是不正确的,因为 actionTwo 在 20 毫秒 (-a-a) 之后发生,而响应又需要 10 毫秒 (-a)。所以第一个 successAction 是在 20ms (10+10) 之后,第二个是在 30ms (20+10) 之后。大理石是:'--b-b'。
Input actions : -a -a
1st http response : -a
2nd http response : -a
Output actions : --b -b
工作代码:
it('should return successAction', () => {
const actions = [actionOne(), actionTwo()];
actions$ = hot('-a-b', { a: actions[0], b: actions[1] });
const response = cold('-a|', { a: data });
userServiceSpy.getSomeDataViaHTTP.and.returnValue(response);
const outcome = successAction({ payload: data });
const expected = cold('--b-b', { b: outcome });
expect(effects.someEffect$).toBeObservable(expected);
});
大理石测试很酷,但它涉及一些您应该准备的黑魔法。我非常建议您仔细阅读 this excellent article 以更深入地了解该主题。
我有一个 Effect,每次它收到一个以上的动作时都会被调用 "kind"
myEffect.effect.ts
someEffect$ = createEffect(() =>
this.actions$.pipe(
ofType(fromActions.actionOne, fromActions.actionTwo),
exhaustMap(() => {
return this.myService.getSomeDataViaHTTP().pipe(
map((data) =>
fromActions.successAction({ payload: data})
),
catchError((err) =>
ObservableOf(fromActions.failAction({ payload: err }))
)
);
})
)
);
在我的测试中,我试图“模拟两个不同的动作,但我总是以错误告终,而如果我尝试一个动作,它就完美无缺
The Before Each part
describe('MyEffect', () => {
let actions$: Observable<Action>;
let effects: MyEffect;
let userServiceSpy: jasmine.SpyObj<MyService>;
const data = {
// Some data structure
};
beforeEach(() => {
const spy = jasmine.createSpyObj('MyService', [
'getSomeDataViaHTTP',
]);
TestBed.configureTestingModule({
providers: [
MyEffect,
provideMockActions(() => actions$),
{
provide: MyService,
useValue: spy,
},
],
});
effects = TestBed.get(MyEffect);
userServiceSpy = TestBed.get(MyService);
});
This works perfectly
it('should return successActionsuccessAction', () => {
const action = actionOne();
const outcome = successAction({ payload: data });
actions$ = hot('-a', { a: action });
const response = cold('-a|', { a: data });
userServiceSpy.getSomeDataViaHTTP.and.returnValue(response);
const expected = cold('--b', { b: outcome });
expect(effects.someEffect$).toBeObservable(expected);
});
This doesn't work
it('should return successAction', () => {
const actions = [actionOne(), actionTwo()];
const outcome = successAction({ payload: data });
actions$ = hot('-a-b', { a: actions[0], b: actions[1] });
const response = cold('-a-a', { a: data });
userServiceSpy.getSomeDataViaHTTP.and.returnValue(response);
const expected = cold('--b--b', { b: outcome });
expect(effects.someEffect$).toBeObservable(expected);
});
这段代码有两个问题。
- 提示getSomeDataViaHTTPreturns两个值。这是错误的,响应与您的第一个示例没有什么不同:'-a|'
- 它期望在 40 毫秒后出现第二个 successAction(--b--b,计算破折号的数量)。这是不正确的,因为 actionTwo 在 20 毫秒 (-a-a) 之后发生,而响应又需要 10 毫秒 (-a)。所以第一个 successAction 是在 20ms (10+10) 之后,第二个是在 30ms (20+10) 之后。大理石是:'--b-b'。
Input actions : -a -a
1st http response : -a
2nd http response : -a
Output actions : --b -b
工作代码:
it('should return successAction', () => {
const actions = [actionOne(), actionTwo()];
actions$ = hot('-a-b', { a: actions[0], b: actions[1] });
const response = cold('-a|', { a: data });
userServiceSpy.getSomeDataViaHTTP.and.returnValue(response);
const outcome = successAction({ payload: data });
const expected = cold('--b-b', { b: outcome });
expect(effects.someEffect$).toBeObservable(expected);
});
大理石测试很酷,但它涉及一些您应该准备的黑魔法。我非常建议您仔细阅读 this excellent article 以更深入地了解该主题。