如何在使用 Jest 和 redux 操作时匹配返回的 Promise [英] how to match a returned Promise in using Jest with redux action

查看:17
本文介绍了如何在使用 Jest 和 redux 操作时匹配返回的 Promise的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将 reactjs 与 redux 一起使用,动作是使用 axios 并返回一个 Promise.我的测试与类型不匹配.我尝试了不同的方法,但最终还是遇到了同样的问题.也试过 https://www.leighhalliday.com/mocking-axios-in-jest-testing-async-functions

I am using reactjs with redux and the action is using axios and returning a Promise. my test is not matching the type. I have tried different ways of doing it but end up with the same problem. also tried https://www.leighhalliday.com/mocking-axios-in-jest-testing-async-functions

    import configureMockStore from 'redux-mock-store'
    //import fetchMock from 'fetch-mock'
    import expect from 'expect' // You can use any testing library
    import axios from 'axios';
    import MockAdapter from 'axios-mock-adapter';
    import * as actions from '../../../app/actions/admin'
    import * as types from '../../../app/reducers/reducer_content'


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

    descri

be('async actions', () => {

  it('FETCH_CONTENT_VIDEO_LIST', () => {
    let mock = new MockAdapter(axios);
      const data = { response: true };
      mock.onGet('/contentvideolist').reply(200, data);


    console.log(types);
    const expectedActions = [{"payload": {}, "type": actions.FETCH_CONTENT_VIDEO_LIST}]
    const store = mockStore({ fetch_content_video_list: [] })
    console.log(actions);
    store.dispatch(actions.fetchContentVideoList());
    expect(store.getActions()).toEqual(expectedActions);
  });
});

这是结果

 expect(received).toEqual(expected)

    Expected value to equal:
      [{"payload": {}, "type": "fetch_content_video_list"}]
    Received:
      [{"payload": {}, "type": "fetch_content_video_list"}]

    Difference:

    - Expected
    + Received

      Array [
        Object {
    -     

"payload": Object {},
    +     "payload": Promise {},
          "type": "fetch_content_video_list",
        },
      ]

actions/admin.js

export const FETCH_CONTENT_VIDEO_LIST = 'fetch_content_video_list';
export function fetchContentVideoList(page, size, where, sort) {
    const request = axios.get(`/api/user/get/content/management/method/video/list/format/json?quiet=1&page=` + page + `&size=` + size + `&where=` + JSON.stringify(where) + `&sort=` + sort);
    return {
        type: FETCH_CONTENT_VIDEO_LIST,
        payload: request
    };
}

更新后出现新错误

Actions must be plain objects. Use custom middleware for async actions.

      23 |     const store = mockStore({ fetch_content_video_list: [] })
      24 |     console.log(actions);
    > 25 |     store.dispatch(actions.fetchContentVideoList());
      26 |     expect(store.getActions()).toEqual(expectedActions);
      27 |   });
      28 | });

更新

    import configureMockStore from 'redux-mock-store'
    import promise from 'redux-promise';
    import expect from 'expect' // You can use any testing library
    import axios from 'axios';
    import MockAdapter from 'axios-mock-adapter';
    import * as actions from '../../../app/actions/admin'
    import * as types from '../../../app/reducers/reducer_content'

const middlewares = [promise]
const mockStore = configureMockStore(middlewares)

describe('async actions', () => {

  it('FETCH_CONTENT_VIDEO_LIST', () => {
    let mock = new MockAdapter(axios);
      const data = { response: true };
      mock.onGet('/contentvideolist').reply(200, data);


    console.log(types);
    const expectedActions = [{"payload": {}, "type": actions.FETCH_CONTENT_VIDEO_LIST}]
    const store = mockStore({ fetch_content_video_list: [] })
    console.log(actions);
    store.dispatch(actions.fetchContentVideoList());
    expect(store.getActions()).toEqual(expectedActions);
  });
});

我添加了 promise 作为中间件

i added promise as middleware

结果

(node:19685) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 3): Error: Request failed with status code 404
(node:19685) [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  tests/jest/actions/admin.test.js
  async actions
    ✕ FETCH_CONTENT_VIDEO_LIST (43ms)

  ● async actions › FETCH_CONTENT_VIDEO_LIST

    expect(received).toEqual(expected)

    Expected value to equal:
      [{"payload": {}, "type": "fetch_content_video_list"}]
    Received:
      []

    Difference:

    - Expected
    + Received

    - Array [
    -   Object {
    -     "payload": Object {},
    -     "type": "fetch_content_video_list",
    -   },
    - ]
    + Array []

      24 |     console.log(actions);
      25 |     store.dispatch(actions.fetchContentVideoList());
    > 26 |     expect(store.getActions()).toEqual(expectedActions);
      27 |   });
      28 | });
      29 |

      at Object.<anonymous> (tests/jest/actions/admin.test.js:26:32)

  console.log tests/jest/actions/admin.test.js:21
    { default: [Function] }

  console.log tests/jest/actions/admin.test.js:24
    { FETCH_CONTENT_VIDEO_LIST: 'fetch_content_video_list',
      fetchContentVideoList: [Function: fetchContentVideoList],
      FETCH_CONTENT_VIDEO_LIST_COUNT: 'fetch_content_video_list_count',
      UPDATE_CONTENT_VIDEO_LIST: 'update_content_video_list',
      fetchContentVideoListCount: [Function: fetchContentVideoListCount],
      updateContentVideoList: [Function: updateContentVideoList] }

已修复

添加了 then 子句.这是正确的方法吗?

added a then clause. is this correct way to do this?

    import configureMockStore from 'redux-mock-store'
import promise from 'redux-promise';
import expect from 'expect' // You can use any testing library
import axios from 'axios';
import * as actions from '../../../app/actions/admin'


const middlewares = [promise]
const mockStore = configureMockStore(middlewares)
const store = mockStore({  })

beforeEach(() => { // Runs before each test in the suite
    store.clearActions();
      });

describe('async actions', () => {


  it('FETCH_CONTENT_VIDEO_LIST', () => {

    const expectedActions = [{"payload": {}, "type": actions.FETCH_CONTENT_VIDEO_LIST}]

    store.dispatch(actions.fetchContentVideoList()).then(() => {
        expect(store.getActions()).toEqual(expectedActions);
    });
  });


  it('FETCH_CONTENT_VIDEO_LIST_COUNT', () => {

        const expectedActions = [{"payload": {}, "type": actions.FETCH_CONTENT_VIDEO_LIST_COUNT}]


        store.dispatch(actions.fetchContentVideoListCount()).then(() => {
            expect(store.getActions()).toEqual(expectedActions);
        });
      });

  it('UPDATE_CONTENT_VIDEO_LIST', () => {

        const expectedActions = [{"payload": {}, "type": actions.UPDATE_CONTENT_VIDEO_LIST}]


        store.dispatch(actions.updateContentVideoList()).then(() => {
            expect(store.getActions()).toEqual(expectedActions);
        });
      });

});

推荐答案

fetchContentVideoList 不会等待 promise 被解析或拒绝,所以 payload 成为未解决的承诺.

fetchContentVideoList doesn't wait for the promise to be resolved or rejected, so the payload becomes the unresolved promise.

解决此问题的一种方法是使用 async/await 方法:

One way to fix this would be to use the async/await method:

export async function fetchContentVideoList(page, size, where, sort) {
    const request = await axios.get('url');
    return {
        type: FETCH_CONTENT_VIDEO_LIST,
        payload: request
    };
}

请参阅 MDN 上的异步文档了解更多信息.

See async docs on MDN for more information.

编辑问题更新

此更改将操作转换为异步操作,这意味着它需要以稍微不同的方式进行处理.在承诺解决后(正如您所做的那样)制定期望是测试操作的一种好方法.

This change turns the action into an asynchronous action, which means that it needs to be handled in a slightly different way. Making the expections after the promise has resolved (as you are doing) is one good way to test the action.

这篇关于如何在使用 Jest 和 redux 操作时匹配返回的 Promise的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆