Redux 传奇测试用例 - jest.spyOn
Redux saga test case - jest.spyOn
对于使用 jest.spyOn() 和 mockImplmentation 的模拟 api 调用,我得到 undefined 作为响应。
Saga.tsx
export function* parseUserData(parsingAction: IParsingAction) {
try {
const skills = yield call(SkillRepository.getAllSkills);
console.log('------skils-----', skills); // undefined
const industries = yield call(IndustryRepository.getAllIndustry);
if (skills.skillGroup && industry.industryGroup)
{
yield put(getSkillsSuccess(skills.skillGroups));
yield put(getIndustriesSuccess(industry.industryGroups));
}
else
{
yield put(bulkUploadError());
}
} catch (error) {
yield put(bulkUploadError());
}
}
Saga.test.tsx
describe('ParseUserData job saga', () => {
const action = {
type: bulkUploadActionType.GET_API_DATA,
payload: {
sheetData: {},
isAdvisor: true,
},
};
const generator = parseUserData(action);
it('Should call skill repository', () => {
const skills = { skillGroups: [] };
const spy = jest.spyOn(SkillRepository, 'getAllSkills');
spy.mockImplementation((): any => {
return (skills);
});
expect(generator.next().value).toEqual(call(SkillRepository.getAllSkills));
spy.mockRestore();
});
});
如有任何帮助,我们将不胜感激。它非常简单,但我坚持这个。
将 sagas 作为纯生成器进行测试时,redux saga 中间件未连接以驱动生成器 - 您必须自己执行此操作。所以 SkillRepository.getAllSkills
实际上并没有被调用,相反你需要提供期望值给 generator.next()
。您可以在测试部分的第一个示例中看到这一点,其中调用 gen.next(chooseColor(color))
来驱动发电机。在你的情况下,你会做类似的事情:
expect(generator.next().value).toEqual(call(SkillRepository.getAllSkills));
expect(generator.next(skills).done).toBe(true);
因为真正执行 call
效果的是 redux saga 中间件,如果你想测试当你的 saga 是 运行 时调用 SkillRepository.getAllSkill
你需要按照 Testing the full Saga
下的示例,其中 runSaga
用于让 redux-saga
驱动发电机,您可以在模块上 mock/spy 查看它们是否被调用。
所以我会将您的测试重写为:
it('Should call skill repository', () => {
const skills = { skillGroups: [] };
const spy = jest.spyOn(SkillRepository, 'getAllSkills');
spy.mockImplementation((): any => {
return (skills);
});
runSaga(
{dispatch: () => {}, getState: () => ({})}, // flesh these out if need be
parseUserData, action
).toPromise().then(() => {
expect(SkillRepository.getAllSkills.mock.calls.length).toBe(1);
spy.mockRestore();
)
});
编辑
对于上面分享的完整 saga 的单元测试:
describe('ParseUserData job saga', () => {
const action = {
type: bulkUploadActionType.GET_API_DATA,
payload: {
sheetData: {},
isAdvisor: true,
},
};
const generator = parseUserData(action);
it('Should call skill repository', () => {
const skills = { skillGroups: [] };
const industries = { industryGroups: [] };
expect(generator.next().value).toEqual(
call(SkillRepository.getAllSkills));
expect(generator.next(skills).value).toEqual(
call(IndustryRepository.getAllIndustry));
expect(generator.next(industries).value).toEqual(
put(getSkillsSuccess(skills.skillGroups)));
expect(generator.next().value).toEqual(
put(getIndustriesSuccess(industries.industryGroups))
);
expect(generator.next().done).toBe(true);
});
对于使用 jest.spyOn() 和 mockImplmentation 的模拟 api 调用,我得到 undefined 作为响应。
Saga.tsx
export function* parseUserData(parsingAction: IParsingAction) {
try {
const skills = yield call(SkillRepository.getAllSkills);
console.log('------skils-----', skills); // undefined
const industries = yield call(IndustryRepository.getAllIndustry);
if (skills.skillGroup && industry.industryGroup)
{
yield put(getSkillsSuccess(skills.skillGroups));
yield put(getIndustriesSuccess(industry.industryGroups));
}
else
{
yield put(bulkUploadError());
}
} catch (error) {
yield put(bulkUploadError());
}
}
Saga.test.tsx
describe('ParseUserData job saga', () => {
const action = {
type: bulkUploadActionType.GET_API_DATA,
payload: {
sheetData: {},
isAdvisor: true,
},
};
const generator = parseUserData(action);
it('Should call skill repository', () => {
const skills = { skillGroups: [] };
const spy = jest.spyOn(SkillRepository, 'getAllSkills');
spy.mockImplementation((): any => {
return (skills);
});
expect(generator.next().value).toEqual(call(SkillRepository.getAllSkills));
spy.mockRestore();
});
});
如有任何帮助,我们将不胜感激。它非常简单,但我坚持这个。
将 sagas 作为纯生成器进行测试时,redux saga 中间件未连接以驱动生成器 - 您必须自己执行此操作。所以 SkillRepository.getAllSkills
实际上并没有被调用,相反你需要提供期望值给 generator.next()
。您可以在测试部分的第一个示例中看到这一点,其中调用 gen.next(chooseColor(color))
来驱动发电机。在你的情况下,你会做类似的事情:
expect(generator.next().value).toEqual(call(SkillRepository.getAllSkills));
expect(generator.next(skills).done).toBe(true);
因为真正执行 call
效果的是 redux saga 中间件,如果你想测试当你的 saga 是 运行 时调用 SkillRepository.getAllSkill
你需要按照 Testing the full Saga
下的示例,其中 runSaga
用于让 redux-saga
驱动发电机,您可以在模块上 mock/spy 查看它们是否被调用。
所以我会将您的测试重写为:
it('Should call skill repository', () => {
const skills = { skillGroups: [] };
const spy = jest.spyOn(SkillRepository, 'getAllSkills');
spy.mockImplementation((): any => {
return (skills);
});
runSaga(
{dispatch: () => {}, getState: () => ({})}, // flesh these out if need be
parseUserData, action
).toPromise().then(() => {
expect(SkillRepository.getAllSkills.mock.calls.length).toBe(1);
spy.mockRestore();
)
});
编辑
对于上面分享的完整 saga 的单元测试:
describe('ParseUserData job saga', () => {
const action = {
type: bulkUploadActionType.GET_API_DATA,
payload: {
sheetData: {},
isAdvisor: true,
},
};
const generator = parseUserData(action);
it('Should call skill repository', () => {
const skills = { skillGroups: [] };
const industries = { industryGroups: [] };
expect(generator.next().value).toEqual(
call(SkillRepository.getAllSkills));
expect(generator.next(skills).value).toEqual(
call(IndustryRepository.getAllIndustry));
expect(generator.next(industries).value).toEqual(
put(getSkillsSuccess(skills.skillGroups)));
expect(generator.next().value).toEqual(
put(getIndustriesSuccess(industries.industryGroups))
);
expect(generator.next().done).toBe(true);
});