我在React Native中测试sagas时遇到了一些问题。
我读过很多例子,但我似乎看不出什么是对单元测试的正确方法。
例如:
我有以下传奇故事:
function* getUsers(action) {
try {
const { id } = action.payload;
const { data } = yield call(api.users.getUsers, { id });
yield put({ type: userConstants.LOAD_USERS, payload: data });
} catch (err) {
yield call(errorHandler, err);
yield put({ type: userConstants.LOAD_USERS_FAIL });
}
}
function* getProfiles(action) {
try {
const { id } = action.payload;
const { data } = yield call(api.users.getProfiles, { id });
yield put({ type: userConstants.LOAD_PROFILES, payload: data });
} catch (err) {
yield call(errorHandler, err);
yield put({ type: userConstants.LOAD_PROFILES_FAIL });
}
}
export function* usersSaga() {
yield takeLatest(userConstants.GET_USERS, getUsers);
yield takeLatest(userConstants.GET_USER_PROFILES, getProfiles);
}
测试文件:
import usersSaga from '../sagas/users/';
describe('Users Saga', () => {
it('should fetch users', () => {
// what should I put in here
// how should my test look like ?
});
})
我的测试应该是什么样子,我应该测试什么工作,有人能给我一个基本的例子吗?
您可以使用Redux Saga测试计划来测试观察者和工作人员sagas。
对于单元测试,Redux Saga测试计划导出一个
testSaga
函数,该函数创建一个模拟传奇,供您断言对的影响
例如
saga.ts
:
import { call, put, takeLatest } from 'redux-saga/effects';
import { api, errorHandler } from './api';
import { userConstants } from './actionTypes';
export function* getUsers(action) {
try {
const { id } = action.payload;
const { data } = yield call(api.users.getUsers, { id });
yield put({ type: userConstants.LOAD_USERS, payload: data });
} catch (err) {
yield call(errorHandler, err);
yield put({ type: userConstants.LOAD_USERS_FAIL });
}
}
export function* getProfiles(action) {
try {
const { id } = action.payload;
const { data } = yield call(api.users.getProfiles, { id });
yield put({ type: userConstants.LOAD_PROFILES, payload: data });
} catch (err) {
yield call(errorHandler, err);
yield put({ type: userConstants.LOAD_PROFILES_FAIL });
}
}
export function* usersSaga() {
yield takeLatest(userConstants.GET_USERS, getUsers);
yield takeLatest(userConstants.GET_USER_PROFILES, getProfiles);
}
actionTypes.ts
:
export const userConstants = {
LOAD_USERS: 'LOAD_USERS',
LOAD_USERS_FAIL: 'LOAD_USERS_FAIL',
LOAD_PROFILES: 'LOAD_PROFILES',
LOAD_PROFILES_FAIL: 'LOAD_PROFILES_FAIL',
GET_USERS: 'GET_USERS',
GET_USER_PROFILES: 'GET_USER_PROFILES',
};
api.ts
:
export const api = {
users: {
async getUsers(params) {},
async getProfiles(params) {},
},
};
export function errorHandler(err) {}
saga.test.ts
:
import { testSaga } from 'redux-saga-test-plan';
import { getProfiles, getUsers, usersSaga } from './saga';
import { userConstants } from './actionTypes';
import { api, errorHandler } from './api';
describe('68294010', () => {
describe('usersSaga', () => {
it('should pass', () => {
testSaga(usersSaga)
.next()
.takeLatest(userConstants.GET_USERS, getUsers)
.next()
.takeLatest(userConstants.GET_USER_PROFILES, getProfiles)
.finish()
.isDone();
});
});
describe('getUsers', () => {
it('should get data', () => {
testSaga(getUsers, { payload: { id: 1 } })
.next()
.call(api.users.getUsers, { id: 1 })
.next({ data: 'teresa teng' })
.put({ type: userConstants.LOAD_USERS, payload: 'teresa teng' })
.finish()
.isDone();
});
it('should handle error', () => {
const err = new Error('network');
testSaga(getUsers, { payload: { id: 1 } })
.next()
.call(api.users.getUsers, { id: 1 })
.throw(err)
.call(errorHandler, err)
.next()
.put({ type: userConstants.LOAD_USERS_FAIL })
.finish()
.isDone();
});
});
describe('getProfiles', () => {
it('should get profile', () => {
testSaga(getProfiles, { payload: { id: 1 } })
.next()
.call(api.users.getProfiles, { id: 1 })
.next({ data: 'teresa teng' })
.put({ type: userConstants.LOAD_PROFILES, payload: 'teresa teng' })
.finish()
.isDone();
});
it('should handle error', () => {
const err = new Error('network');
testSaga(getProfiles, { payload: { id: 1 } })
.next()
.call(api.users.getProfiles, { id: 1 })
.throw(err)
.call(errorHandler, err)
.next()
.put({ type: userConstants.LOAD_PROFILES_FAIL })
.finish()
.isDone();
});
});
});
单元测试结果:
PASS src/stackoverflow/68294010/saga.test.ts
68294010
usersSaga
✓ should pass (3 ms)
getUsers
✓ should get data (1 ms)
✓ should handle error (1 ms)
getProfiles
✓ should get profile (1 ms)
✓ should handle error
----------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 50 | 100 |
actionTypes.ts | 100 | 100 | 100 | 100 |
api.ts | 100 | 100 | 0 | 100 |
saga.ts | 100 | 100 | 100 | 100 |
----------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 5 passed, 5 total
Snapshots: 0 total
Time: 4.04 s