我对redux-saga还比较陌生,并且很难测试这段代码:
import { normalize } from 'normalizr';
export function* normalizeResponse(denormalized, schema) {
const normalized = yield call(normalize, denormalized, schema);
return normalized;
}
export function* request(apiFn, action, schema) {
try {
yield put(requestStart({ type: action.type }));
const denormalized = yield call(apiFn, action.payload, action.meta);
const normalized = yield call(normalizeResponse, denormalized, schema);
yield put(requestSuccess({ type: action.type }));
return normalized;
} catch (e) {
if (__DEV__ && !__TEST__) {
Alert.alert('Something went wrong');
console.log(`Error in request saga: ${action.type}`, e);
}
if (action.type) {
const payload = { type: action.type, error: e };
const meta = action.payload || {};
yield put(requestFailure(payload, meta));
}
}
}
export function* photosShow() {
while (true) {
const action = yield take(t.PHOTOS_SHOW);
const normalized = yield call(request, api.show, action, {
photo: schema.photo,
});
if (normalized) yield put(setEntities(normalized));
}
}在网上,我发现了一些redux测试包和一些教程,但它们似乎没有一个比基础更多。下面是这个传奇故事的一步一步的运作方式:
photosShow是用一个Flux标准操作调用的,有效载荷为{ id: 1}request,这是一个实用函数,用于发出API请求,然后将响应规范化。requestStart操作。setEntities存储在redux状态(回到photosShow中)任何帮助前进,如何进行这将是非常感谢的。
发布于 2019-05-07 06:54:43
我也很难阅读所有的redux-saga测试资源..。找不到合适的解决方案(至少对我来说是这样)。
我最后的结果是:
最后:我触发了萨加,我发现他们触发了其他的东西。
我认为萨加是一个黑匣子,我检查他们是否尊重与所有其他部分的应用程序的合同。
我以身份验证saga测试为例(我破坏了许多测试良好实践,我知道,它来自于我使用saga的早期测试)(关于renderWithRedux和spyUtil函数,请参阅下面):
describe("Login flow with valid credentials", () => {
let user = "stefano";
let pwd = "my_super_secret_password";
let app;
let spies;
// const spiedConsole = spyConsole();
beforeAll(() => {
app = renderWithRedux(<></>);
spies = {
LOGIN_SUCCESS_creator: spyUtil(authActions, "LOGIN_SUCCESS_creator"),
navigate: spyUtil(ReachRouter, "navigate"),
postLogin: spyUtil(authNetwork, "postLogin", postLoginOk),
redirectBackFromLoginPage: spyUtil(navigationData, "redirectBackFromLoginPage")
};
});
test("1 - the login API should be called as soon as the LOGIN_REQUEST action is dispatched", async () => {
app.store.dispatch(authActions.LOGIN_REQUEST_creator(user, pwd));
expect(spies.postLogin.spy).toHaveBeenCalledWith(user, pwd);
});
test("2 - then when the login API is successfull, a LOGIN_SUCCESS action should be dispatched with the tokens", async () => {
expect(spies.LOGIN_SUCCESS_creator.spy).toHaveBeenCalledWith(
expect.any(String),
expect.any(String)
);
});
test("3 - then the router should be asked to make a redirect to the initial location", async () => {
expect(spies.redirectBackFromLoginPage.spy).toHaveBeenCalled();
expect(spies.navigate.spy).toHaveBeenCalledWith(expect.stringMatching(/\//));
});
afterAll(() => {
spies.values().forEach(obj => obj.spy.mockRestore());
// spiedConsole.mockRestore();
cleanup();
});
});一步一步地:-我用一个工作的Redux+Saga商店呈现一个空的应用程序
app = renderWithRedux(<></>);spies = {
LOGIN_SUCCESS_creator: spyUtil(authActions, "LOGIN_SUCCESS_creator"),
navigate: spyUtil(ReachRouter, "navigate"),
postLogin: spyUtil(authNetwork, "postLogin", postLoginOk),
redirectBackFromLoginPage: spyUtil(navigationData, "redirectBackFromLoginPage")
};其中:
LOGIN_SUCCESS_creator是一个动作创建者navigate来自Reach路由器postLogin发出AJAX请求(用一个假函数模拟它,几乎立即返回一个“成功”响应(但解决了一个承诺))redirectBackFromLoginPage是一个函数,它再次(在某些条件下)使用navigate实用程序。- I trigger the `LOGIN_REQUEST` action, and I expect that the AJAX trigger function has been called with the right credentials
test("1 - the login API should be called as soon as the LOGIN_REQUEST action is dispatched", async () => {
app.store.dispatch(authActions.LOGIN_REQUEST_creator(user, pwd));
expect(spies.postLogin.spy).toHaveBeenCalledWith(user, pwd);
});LOGIN_SUCCESS操作是否将与auth令牌一起发送。test("2 - then when the login API is successfull, a LOGIN_SUCCESS action should be dispatched with the tokens", async () => {
expect(spies.LOGIN_SUCCESS_creator.spy).toHaveBeenCalledWith(
expect.any(String),
expect.any(String)
);
});/)test("3 - then the router should be asked to make a redirect to the initial location", async () => {
expect(spies.redirectBackFromLoginPage.spy).toHaveBeenCalled();
expect(spies.navigate.spy).toHaveBeenCalledWith(expect.stringMatching(/\//));
});afterAll(() => {
spies.values().forEach(obj => obj.spy.mockRestore());
// spiedConsole.mockRestore();
cleanup();
});这是“我的”(它来自肯特C.道兹) renderWithRedux函数
// @see https://github.com/kentcdodds/react-testing-library/blob/master/examples/__tests__/react-redux.js
export function renderWithRedux(ui, { initialState, store = configureStore() } = {}) {
return {
...render(
<div>
<Provider store={store}>{ui}</Provider>
</div>
),
// adding `store` to the returned utilities to allow us
// to reference it in our tests (just try to avoid using
// this to test implementation details).
store
};
}其中,configureStore是is的一个函数,它使用各种中间件构建整个Redux商店。
这是我的spyUtil函数
/**
* A all-in-one spy and mock function
* @param {object} obj
* @param {string} name
* @param {function} mockFunction
*/
export function spyUtil(obj, name, mockFunction = undefined) {
const spy = jest.spyOn(obj, name);
let mock;
if (mockFunction) {
mock = jest.fn(mockFunction);
obj[name].mockImplementation(mock);
}
return { spy, mock };
}请注意,这只是身份验证流之一,我没有在这里报告所有的情况。
我想知道你对此的想法
https://stackoverflow.com/questions/55734309
复制相似问题