Redux Saga Test - mosinn/DOCS-n-Snippets-n-Steps GitHub Wiki
Each line of saga is entire method on its own, of which, the each next() of test case, executes ONE line of actual saga at a time.
So putting break point in each line of actual saga and actual test's next(), keeps break point jumping between test and saga, very useful, indeed for checking each line return is as per previous next(arg)
Saga ASSERTION failure LOG is shallow. How to expand it to observe n-level nested differences in EFFECT arguments ?
// Add to the top of TEST file
import util from 'util'
util.inspect.defaultOptions.depth = null
Use the logging as there is NO OTHER WAY if there is no DIFF in Failed Test Case :)
Expected
--------
{
'@@redux-saga/IO': true,
combinator: false,
type: 'CALL',
payload: {
context: null,
fn: [Function: submitPeriodicPayment],
args: [
'http://localhost',
'token',
Eg:
Test Case and Code Logs:
export const productSelector = (state: Store) => state.xyz.formData.data.product;
export function* fetchAccountsWorker(action: ActionType<typeof xyzActions.fetchAccounts>) {
try {
const product: Product = yield select(productSelector);
const url = getFromNonGeneratorHelperFunc(product);
const response: AxiosResponse<Account[]> = yield call(fetchAccounts, url, product, action);
yield put(xyzActions.fetchAccountsSucceeded(response.data));
} catch (e) {
console.error('Failed to fetch accounts', e);
}
MUST DEBUG Saga Test while running in Intellij to understand flow of TEST and mocks
next with args does two things
sets fake but IMPORTANT input for upcoming effect
advances saga
Take Saga test with a pinch of salt and not too seriously. These pass most of time if under test code is changed. Just debug make sure all lines are covered and dust it away !!!
it('logs to console if failed to fetch account info', () => {
let myActionRef: ActionType<CreateViewEditActionType.FETCH_TRACE_ACCOUNTS> = {
type: CreateViewEditActionType.FETCH_TRACE_ACCOUNTS
};
testSaga(fetchAccountInfoWorker, myActionRef)
.next() // Always needed to reach the line
.select(productSelector) // Assert select effect is called with a given selector. Note, originally selector in real code was anonymous func, but that gives an issue in select() effect test
.next(mockSelectedProductAsIfReturnedBySelectJustAbove)//This will be passed to getFromNonGeneratorHelperFunc() as this is what will be fake returned by previous select. Url will be real based on this fake input
.call(fetchTraceAccounts, 'url1CreatedByHelperFromFakeProductInput', myActionRef)
.next(mockApiResponseFromCallEffect)
.put(createViewEditActions.fetchTraceAccountsSucceeded(mockApiResponseFromCallEffect)) // Assert put effect is passed an expected mock input
.throw({message: "msg", name: "error"})
.isDone();
// tips - testSaga ONLY - MUST DEBUG Saga Test while running in Intellij to understand flow of TEST and mocks - next with args does two things. Sets fake but IMPORTANT input for upcoming effect and advances saga
expect(mockConsoleError).toHaveBeenCalled();
});