【问题标题】:Cannot read property '.then' of undefined when testing async action creators with redux and react使用 redux 测试异步操作创建者并做出反应时,无法读取未定义的属性“.then”
【发布时间】:2017-12-09 04:48:23
【问题描述】:

我正在尝试使用 react、redux-mock-store 和 redux 编写一些测试,但我不断出错。可能是因为我的Promise还没解决?

fetchListing() 动作创建器在我在开发和生产环境中尝试时确实有效,但我在通过测试时遇到问题。

错误信息

(node:19143) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 3): SyntaxError
(node:19143) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
 FAIL  src/actions/__tests__/action.test.js
  ● async actions › creates "FETCH_LISTINGS" when fetching listing has been done

    TypeError: Cannot read property 'then' of undefined

      at Object.<anonymous> (src/actions/__tests__/action.test.js:44:51)
          at Promise (<anonymous>)
      at Promise.resolve.then.el (node_modules/p-map/index.js:42:16)
          at <anonymous>
      at process._tickCallback (internal/process/next_tick.js:169:7)

  async actions
    ✕ creates "FETCH_LISTINGS" when fetching listing has been done (10ms)

action/index.js

// actions/index.js
import axios from 'axios';

import { FETCH_LISTINGS } from './types';

export function fetchListings() {

  const request = axios.get('/5/index.cfm?event=stream:listings');

  return (dispatch) => {
    request.then(( { data } ) => {
      dispatch({ type: FETCH_LISTINGS, payload: data });
    });
  }
};

action.test.js

// actions/__test__/action.test.js

import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import { applyMiddleware } from 'redux';
import nock from 'nock';
import expect from 'expect';

import * as actions from '../index';
import * as types from '../types';


const middlewares = [ thunk ];
const mockStore = configureMockStore(middlewares);

describe('async actions', () => {
  afterEach(() => {
    nock.cleanAll()
})


it('creates "FETCH_LISTINGS" when fetching listing has been done', () => {
  nock('http://example.com/')
    .get('/listings')
    .reply(200, { body: { listings: [{ 'corpo_id': 5629, id: 1382796, name: 'masm' }] } })

    const expectedActions = [
      { type: types.FETCH_LISTINGS }, { body: { listings: [{ 'corpo_id': 5629, id: 1382796, name: 'masm' }] }}
    ]

    const store = mockStore({ listings: [] })

    return store.dispatch(actions.fetchListings()).then((data) => {
      expect(store.getActions()).toEqual(expectedActions)
    })
  })
})

【问题讨论】:

    标签: reactjs redux jestjs redux-mock-store


    【解决方案1】:

    store.dispatch(actions.fetchListings()) 返回undefined。你不能打电话给.then

    redux-thunk code。它执行您返回的函数并将其返回。您在fetchListings 中返回的函数不返回任何内容,即undefined

    试试

    return (dispatch) => {
        return request.then( (data) => {
          dispatch({ type: FETCH_LISTINGS, payload: data });
        });
      }
    

    之后,您仍然会遇到另一个问题。您不会在then 中返回任何内容,您只会发送。这意味着下一个then 得到undefined 参数

    【讨论】:

    • fetchListings() 在我使用它时实际上可以工作 - 我可以在我的应用程序上看到数据 - 但是有没有更好的方法来编写该函数? test 本身呢,我该怎么写呢?
    • 为异步代码编写测试可能具有挑战性。 redux-saga 相对于 redux-thunk 的主要卖点之一是易于测试,因此您可能需要查看该库。
    • 当然 redux-saga 更容易测试,因为它只使用普通对象,但 redux-thunk 也应该很容易测试。这里的问题是他如何处理承诺(以及其他一些事情)。查看我的更新答案
    • 您找到测试的解决方案了吗?我有相同的测试设置并得到相同的错误。
    • @SzilardMagyar 老实说我不记得了。这是我正在从事的一个旧项目。我会在接下来的几天里再次检查,如果我发现了什么,我会在这里发布:)
    【解决方案2】:

    我也知道这是一个旧线程,但您需要确保在 thunk 中返回异步操作。

    在我的想法中,我需要:

    return fetch()
    

    异步操作,它起作用了

    【讨论】:

      【解决方案3】:

      你的动作创建者应该返回一个promise,如下所示:

      // actions/index.js
      import axios from 'axios';
      
      import { FETCH_LISTINGS } from './types';
      
      export function fetchListings() {
        return (dispatch) => {
          return axios.get('/5/index.cfm?event=stream:listings')
          .then(( { data } ) => {
            dispatch({ type: FETCH_LISTINGS, payload: data });
          });
        }
      };

      【讨论】:

        【解决方案4】:

        我知道这是一个旧线程。但我认为问题在于您的动作创建者不是异步的。

        试试:

        export async function fetchListings() {
          const request = axios.get('/5/index.cfm?event=stream:listings');
          return (dispatch) => {
            request.then(( { data } ) => {
              dispatch({ type: FETCH_LISTINGS, payload: data });
            });
          }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-02-27
          • 2019-01-29
          • 1970-01-01
          • 1970-01-01
          • 2018-11-18
          • 2021-12-25
          • 2019-07-05
          • 2017-06-18
          相关资源
          最近更新 更多