我有这个史诗,需要测试的帮助,对异步方法的史诗调用(来自运算符),它使用了延迟运算符
export const getAll$ = (
action$: any,
state: { value: TStore },
{ stock, Error }: TDependencies
) => {
return action$.pipe(
ofType(getAll.toString()),
map(({ meta: { failures} }) => ({
failures,
})),
switchMap(({ failures }) => {
return merge(
of(getAllStart()),
// call api service stock.getAll, this is async
from(stock.getAll()).pipe(
// wait a 1 second, not matter if stock.getAll finish early
delay(OPERATION_DELAY),
switchMap((response: TGetAllResponse) => {
if(response instanceof Error) {
return throwError(response);
}
return of(
getAllSuccess()
);
}),
catchError((error) => {
return failures === 0 ?
of(getAllFailure({ error }))
:
of(getAll({
failures: failures + 1,
})).pipe(
delay(FAILURE_RETRY_TIME),
);
}),
// "cancel" this epic if getAllAbort action is emitted
takeUntil(
action$.ofType(
getAllAbort.toString()
)
)
)
)
})
)
};
这是我的考试
import { ActionsObservable } from 'redux-observable';
// some mocking
const state = { value: {} };
const dependencies = {
api: {},
stock: {
getAll() {
return [];
}
},
Error: class Error {},
};
describe('stock epic', () => {
it('should return all products', (done) => {
// start epic getAll$
getAll$(ActionsObservable.of(getAll()), state, dependencies).subscribe((action) => {
console.log(action); // { type: 'STOCK/GET_ALL_START' }
done();
});
});
});
如果看到console.log(action);
仅返回{ type: 'STOCK/GET_ALL_START' }
如果我使用.toArray()
,则测试永无止境
我正在发布lorem impsun,因为堆栈溢出抱怨我的问题
Lorem ipsum dolor atmet,奉献自若。 Proin ac blandit leo。菜豆未播种或未播种。菜豆非feugiat lorem,neultricies quam。在porttitor bibendum facilisis。 Donec euismod imperdiet tincidunt。 Mauris enim ante,susculit iaculis mi et,convallis fermentum ante。 Vestibulum eget purus pharetra,finibus velit,porta metus。 Vivamus interdum lobortis elit,dignissim tempor sem。 Nam礼仪,舒张期舒张期,尼古拉·伊库图斯·托马斯·托,非索利丁定居者。 Nam vel lacus feugiat lorem venenatis interdum。
[几个小时后,我找到了解决方案,如果您的史诗使用from
运算符,则无法对其进行测试,则需要模拟该运算符,就我而言,我只是将此运算符映射为of
运算符很容易,在您的根项目文件夹中创建一个名为__mocks__
的文件夹,并在其中创建一个名为rxjs.js
的js文件,然后将此代码放入其中]
const rxjs = jest.requireActual('rxjs'); rxjs.from = rxjs.of; module.exports = rxjs;
然后用于测试您是否需要使用类
TestScheduler
,它在rxjs/testing
中可以作为导出常量使用
代码会这样
import { ActionsObservable } from 'redux-observable';
import { TestScheduler } from 'rxjs/testing';
// your epics to be tested
import epics from './stock';
// actions that you epic will emit
import {
getAll,
getAllStart,
getAllSuccess,
} from '../actions/stock';
// mock the state param (if your epic use it)
import { initialState } from '../reducers/stock';
const state = {
value: {
stock: initialState,
},
};
// mock your dependencies param
const dependencies = {
api: {},
stock: {
getAll() { // in my real code, this is a promise, here is just a normal function, perfect to be use with the of operator
return [];
},
},
Error: class Error {},
};
describe('stock epic', () => {
it('should return all products', (done) => {
// this is just copy-paste
const testScheduler = new TestScheduler((actual, expected) => {
expect(actual).toStrictEqual(expected);
});
testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions, flush }) => {
expectObservable(
epics.getAll$(
ActionsObservable.of(getAll()), // transform action to action$
state, // pass mocked state
dependencies // pass mocked dependencies
)
).toBe(
// my epic has a delay(1000) call
'a 999ms (b|)', {
a: getAllStart(),
b: getAllSuccess()
}
);
done();
});
});
});