简体   繁体   中英

How to Jest spyOn a function in a return block

I am trying to spyOn promise1 with a mock implementation (resolved promise with a result of {abc: 'efg'} . However, I am getting the error of Cannot read property 'abc' of undefined . How do I ensure that my mock implementation of promise1 is used?

export const test = (id) => (dispatch) => {
    // do something
    return (
        promise1(id)
            .then((result1.abc) => {
                // do something 
            })
            .then((result2) =>
                promise2(result2)
                    .then((result3) => {
                        dispatch(showNotification({type: 'success'}),
                    })
                    .catch((err) => {
                        dispatch(showNotification({type: 'timeout'}),
                        throw new Error(err);
                    })
            )
            .catch((err) => {
                dispatch(
                        dispatch(showNotification({type: 'failed'}),
                );
            })
    );
};
describe("test", () => {
    it("dispatches success notification if promise2 returns a resolved promise", async () => {

        const promise1 = jest.spyOn(api, "promise1")
        .mockImplementation(() => Promise.resolve({abc: 'efg'}))

        const showNotification = jest.spyOn(actions, 'showNotificationAction')

        await test(1)(dispatch);

        expect(showNotification).toHaveBeenCalledWith(
            {
                type: 'success',
            })
    });
})```

Here is the unit test solution:

actions.ts :

import { promise1, promise2 } from './api';

export const showNotification = (action) => {
  return {
    ...action,
    payload: {},
  };
};

export const someAction = (id) => (dispatch) => {
  return promise1(id)
    .then((result1) => {
      return result1.abc;
    })
    .then((result2) =>
      promise2(result2)
        .then((result3) => {
          dispatch(showNotification({ type: 'success' }));
        })
        .catch((err) => {
          dispatch(showNotification({ type: 'timeout' }));
          throw new Error(err);
        }),
    )
    .catch((err) => {
      dispatch(dispatch(showNotification({ type: 'failed' })));
    });
};

api.ts :

export const promise1 = (id) => Promise.resolve({ abc: 'real abc' });
export const promise2 = (data) => Promise.resolve('real promise2 data');

actions.test.ts :

import * as actions from './actions';
import * as api from './api';

describe('test', () => {
  it('dispatches success notification if promise2 returns a resolved promise', async () => {
    const promise1Spy = jest.spyOn(api, 'promise1').mockImplementation(() => Promise.resolve({ abc: 'efg' }));
    const promise2Spy = jest.spyOn(api, 'promise2').mockResolvedValueOnce('fake promise2 data');
    const showNotification = jest.spyOn(actions, 'showNotification');
    const dispatch = jest.fn();

    await actions.someAction(1)(dispatch);

    expect(promise1Spy).toBeCalledWith(1);
    expect(promise2Spy).toBeCalledWith('efg');
    expect(showNotification).toHaveBeenCalledWith({
      type: 'success',
    });
    expect(dispatch).toBeCalledWith({ type: 'success', payload: {} });
  });
});

Unit test results with coverage report:

 PASS  src/stackoverflow/59796811/actions.test.ts
  test
    ✓ dispatches success notification if promise2 returns a resolved promise (8ms)

------------|----------|----------|----------|----------|-------------------|
File        |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
------------|----------|----------|----------|----------|-------------------|
All files   |    68.75 |      100 |       60 |    76.92 |                   |
 actions.ts |       75 |      100 |       75 |    72.73 |          21,22,26 |
 api.ts     |       50 |      100 |        0 |      100 |                   |
------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        6.272s, estimated 12s

Source code: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/59796811

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