酶集成测试:axios.get 调用未在 redux-saga 中执行
Posted
技术标签:
【中文标题】酶集成测试:axios.get 调用未在 redux-saga 中执行【英文标题】:Enzyme integration testing: axios.get call not being executed in redux-saga 【发布时间】:2021-03-14 14:35:43 【问题描述】:我正在尝试为触发 redux saga 的动作创建者设置测试。
我的 saga 从本地烧瓶服务器检索一个单词(将始终返回相同的单词),然后显示该单词。这不是我的真实案例,但我试图从简单的事情开始......
当我使用我的 react 应用程序中的按钮触发它们时,我的 action creator 和 saga 会按预期工作(该词是从服务器检索的,存储在我的 redux 存储中,并在我的 react 组件中使用选择器显示),但我无法让测试成功。
我只想测试 redux 部分,而不是实际渲染的 react 组件(不确定这是否是我的问题的一部分)
我使用 Enzyme 进行测试,我的商店已正确创建并且可以发送操作。我还可以看到控制台日志正在调用我的 saga:
我的测试代码:
import Store from 'redux';
import RootState from '../root.reducer';
import storeFactory from '../../../test/testUtils';
import getSecretWord from './secret-word.actions';
describe('getSecretWord action creator', () =>
let store: Store<RootState>;
beforeEach(() =>
store = storeFactory();
);
test('add response word to state', () =>
const secretWord = 'party';
store.dispatch(getSecretWord());
const newState = store.getState();
console.log('new state: ' + newState.secretWord);
expect(newState.secretWord).toBe(secretWord);
);
);
还有我的传奇功能:
export function* getSecretWordSaga(action: getSecretWordAction): Generator<ForkEffect | CallEffect | PutEffect, void, unknown>
try
console.log('getSecretWordSaga() saga started');
console.log('before axios query call:');
const response:any = yield call(api.get, '/api/word');
// const response = data: word: 'party', status:200
console.log('axios query returned: ');
console.log(response);
yield put(setSecretWord(response.data.word));
console.log('getSecretWordSaga() saga finsshed');
catch (err)
console.log('error occured:');
console.log(err);
console.log('getSecretWordSaga() saga finsshed with errors');
export function* getSecretWordSagaStart(): Generator<
ForkEffect<never>,
void,
unknown
>
yield takeLatest(SecretWordActionTypes.GET_SECRET_WORD, getSecretWordSaga);
axios api 非常基础,它包含两个用于日志记录的拦截器:
import axios from 'axios';
export const api = axios.create(
baseURL: 'http://localhost:5000',
responseType: 'json',
);
api.interceptors.request.use(request =>
console.log('Starting Request', JSON.stringify(request, null, 2))
return request
)
api.interceptors.response.use(response =>
console.log('Response:', JSON.stringify(response, null, 2))
return response
)
我可以在日志中(在“npm test”中)看到“在 axios 查询调用之前”这一行的日志和请求拦截器的一个 console.log(那里一切看起来都很好),但没有更多日志之后(不成功也不出错)
如果我注释掉“yield call..”并对响应进行硬编码(如下面注释掉的行),我的传奇故事会一直运行到最后,并且我的测试会成功。
为什么没有执行 yield Call(api.get, '/api/word') (而且我没有收到任何错误消息)?
我认为代码是正确的,因为它在 react 中执行时运行良好。我的烧瓶服务器显然也在运行,我可以在烧瓶应用程序中看到正在运行的测试没有调用 api。
我显然打算模拟那个 api 调用,但在那里也遇到了一些问题,这就是为什么我首先想让真正的 api 调用工作。
【问题讨论】:
我还尝试创建一个函数:function fakeApi(): any return data: word: 'party', status:200;
,然后在 yield 调用中调用该函数:const response:any = yield call(fakeApi);
,这样就可以工作了。在 axios.get 看来问题确实是
【参考方案1】:
在尝试了许多不同的方法来添加超时之后,将测试函数设置为异步并在 Promise 中添加 setTimeout 确实有效。 这并不理想,因为我必须将超时设置为特定值,但我想不出更好的方法来让它工作。
test("add response word to state", async () =>
const secretWord = 'party';
store.dispatch(getSecretWord());
await new Promise(res => setTimeout(res, 1000));
const newState = store.getState();
console.log('new state: ' + newState.secretWord);
expect(newState.secretWord).toBe(secretWord);
);
【讨论】:
以上是关于酶集成测试:axios.get 调用未在 redux-saga 中执行的主要内容,如果未能解决你的问题,请参考以下文章
在“if”语句中没有调用模拟函数 - 用玩笑和酶反应应用程序测试?