在所有示例中,我发现每个人都在他们的sagas上使用yield call()
,yield put()
等。现在,我有了一个传奇,它无需执行yield call()
就可以执行一个函数。该函数在选择效果之后和调用效果之前执行(请参见下面的service
变量代码。该函数返回类的实例,它不是网络请求或诺言。
这个传奇作品很好,但是我不确定如何测试它。在产生效果的同时使用redux-sagas-test-plan
效果很好,但是一旦删除效果(从.provide()
中删除效果,测试就会失败。
佐贺
export function* getDetails() {
try {
const config = yield select(getProperties());
const service = getService(config);
const data = yield call([service, service.getDetails]);
yield put(success(data));
} catch(e) {
yield put(failure());
}
}
测试
import { getDetails as detailsSaga } from '...';
const data = {};
it('should succeed getting details', async () => {
await expectSaga(detailsSaga)
.provide([
[select(getProperties), {}],
[call([serviceMock, serviceMock.getDetails]), data]
])
.put(success(data))
.dispatch(fetchDetails())
.silentRun();
});
测试的预期结果是让success(data)
创建者执行,但我得到failure()
创建者作为实际值。
Expected
--------
{ '@@redux-saga/IO': true,
combinator: false,
type: 'PUT',
payload:
{ channel: undefined,
action:
{ type: 'FETCH_DETAILS_SUCCESS',
data: { } } } }
Actual:
------
1. { '@@redux-saga/IO': true,
combinator: false,
type: 'PUT',
payload:
{ channel: undefined,
action: { type: 'FETCH_DETAILS_FAILURE' } } }
答案 0 :(得分:1)
每次在传奇中调用函数时,都应使用call
效果。最好使用它,而不是像已经完成的那样直接调用该函数。它会返回与直接调用时相同的数据,并且由于您不必模拟或监视任何东西,因此使测试变得更加容易。
示例:
export function* getDetails() {
try {
const config = yield select(getProperties());
const service = yield call(getService, config);
const data = yield call([service, service.getDetails]);
yield put(success(data));
} catch(e) {
yield put(failure());
}
}
答案 1 :(得分:1)
根据我发现的其他示例,这是我的解决方案:
import { call } from 'redux-saga-test-plan/matchers';
beforeEach(() => {
service = getService({});
data = { /* ... */ });
});
it('should succeed getting details', async () => {
await expectSaga(detailsSaga)
.provide([
[select(getProperties), {}],
[call.fn(service.getDetails), data]
])
.put(success(data))
.dispatch(fetchDetails())
.silentRun();
});
我必须使用来自redux-saga-test-plan/matchers
的调用效果,并创建由getService返回的实际实例。由于某种原因,模拟无法在此处使用。
我不清楚为什么会这样工作的细节,但是我写这个答案只是为了防万一有人也想实现这个目的。注意:我同意另一个答案,所有功能都应使用yield call
来调用,但是在此我不被要求这样做。