简体   繁体   中英

Async Action creator test cases using jest in react

I am new to writing the test cases in react. Here, I have an action creator which is like ,

export function fetchUserJd() {
  return (dispatch) => {
    let url = FETCH_JD_ROOT_URL + page + "&" + size;
    dispatch({
      type: REQUEST_INITIATED
    })
    get(url)
      .then((response) => {
        console.log("response data",response.payload)
        if (response.status === 200) {
          dispatch({
            type: REQUEST_SUCCESSED,
          });
          dispatch({
            type: FETCHING_JOBDESCRIPTION_SUCCESS,
            data: response.payload,
          }
          )
        }
        else {
          dispatch({
            type: REQUEST_SUCCESSED
          })
          toastr.error("Error while fetching Job Description, Please check again");
          if (response.status === "") {
            toastr.error('Our server is down. Please check again');
          }
          dispatch({
            type: FETCHING_JOBDESCRIPTION_FAILED,
            data: response.status,
          });
          if (response.status === 401) {
            toastr.error('Please Login Again');
            localStorage.clear();
            history.push('/');
          }
        }
      })
  }
};

So, Here I am trying to write the test case for this.

So, what I have tried is ,

beforeEach(function () {
    moxios.install();
  });

  afterEach(function () {
    moxios.uninstall();
  });

  it('creates GET_POSTS_SUCCESS after successfuly fetching postse', () => {
    moxios.wait(() => {
      const request = moxios.requests.mostRecent();
      console.log("request is",request);
      request.respondWith({
        status: 200,
        response: dataResponse,
      });
    });

    const expectedActions = [
      { type: 'FETCHING_JOBDESCRIPTION_SUCCESS', data: dataResponse },
    ];

    const store = mockStore({ data: {} })

    return store.dispatch(actions.fetchUserJd()).then(() => {
      // return of async actions
      expect(store.getActions()).toEqual(expectedActions);
    });
  });

Now, I am getting this error which is like,

● Header component actions › creates GET_POSTS_SUCCESS after successfuly fetching postse

    TypeError: Cannot read property 'then' of undefined

      at Object.it (src/modules/header/actions/_tests_/index.test.js:64:53)
      at Promise.resolve.then.el (node_modules/p-map/index.js:46:16)
      at process._tickCallback (internal/process/next_tick.js:109:7)

Now,Here I actually not understanding why this error is getting appeared.

As I am calling an action and then I am checking that ,as it is calling the expected or not.

export const get = (url) =>
    axios.get(
        url,
        {
            headers: {
                "Authorization": localStorage.getItem("access_token") !== null ? `Bearer ` + localStorage.getItem("access_token") : null,
                "Content-Type": "application/json"
            }
        }
    ).then(data => {
        if (data.status === HttpStatus.OK) {
            return {
                status: data.status,
                payload: data.data
            };
        }
    }).catch(err => {
        return {
            status: err.response.data,
            payload: null
        };
    });

So, Can any one help me with this issue ?

I think your error comes from here but it's not the problem.

return store.dispatch(actions.fetchUserJd()).then(() => {
  // return of async actions
  expect(store.getActions()).toEqual(expectedActions);
});

This part of your code tries to use the 'then' function of dispatch(which doesn't return a Promise at the moment). It is not something that returns a Promise. The initial call to actions.fetchUserJd() doesn't have any asynchronous behavior, it returns a function that has access to dispatch, and that function makes an API call(asynchronous) but handles the .then() internally and doesn't return it.

This means that to be able to wait for it to be done. You could make the return of your action a Promise, like in the example for mocking async actions .

His example is below

function fetchData () {
  return dispatch => {
    return fetch('/users.json') // Here returning the .then() of the fetch(equivalent of your get) is returning a promise, that's why for him the .then() call on the dispatch works in his tests !
      .then(() => dispatch(success()))
  };
}

Then you could use your original code.

return store.dispatch(actions.fetchUserJd()).then(() => {
  // return of async actions
  expect(store.getActions()).toEqual(expectedActions);
});

Completely unrelated thing to note is that you don't directly use the rejected handler function of the get call in your action. ex:

get('http://localhost:3000/example')
   .then(
   (successData) => {
       // Do whatever you want to in case of positive resolution of the get call...
       // Will contain your response code and your data.
    },
    (rejectData) => {
       // Do whatever you want if the request fails, its error data is caught inside rejectData
    }
)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM