酶集成测试: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 中执行的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 jest 和酶测试 API 调用?

在“if”语句中没有调用模拟函数 - 用玩笑和酶反应应用程序测试?

酶测试问题返回未定义

使用 Enzyme 进行 Storybook JS 集成测试 - 状态更改被覆盖

Axios 'Get' 函数未调用

如何使用酶、笑话和反应测试材料设计事件监听器