首页 > 解决方案 > 酶集成测试:axios.get 调用未在 redux-saga 中执行

问题描述

我正在尝试为一些触发 redux 传奇的动作创建者设置测试。

我的传奇从本地烧瓶服务器检索一个词(将始终返回相同的词),然后显示该词。这不是我的真实案例,但我试图从简单的事情开始......

当我在我的反应应用程序中使用按钮触发它们时,我的动作创建者和传奇按预期工作(该词是从服务器检索的,存储在我的 redux 存储中,并在我的反应组件中使用选择器显示),但我无法获得测试成功。

我只想测试 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 调用工作。

标签: testingaxiosintegrationenzymeredux-saga

解决方案


在尝试了许多不同的方法来添加超时之后,将测试功能设置为异步并在 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);

});


推荐阅读