Testing a function that returns an object with a function - JavaScript (Jest)

别说谁变了你拦得住时间么 提交于 2020-03-05 06:02:11

问题


I have a situation where I am facing an issue regarding unit testing of a function. There is a function SOP3loginConfig which returns an object, within that object we have a function isSOP3 that returns a boolean, I want to test this function and cover the test part of it.

The actual implementation of the function sop3login.ts

export const SOP3loginConfig = (props: IVariables) => {
  const { i18n } = props;
  return {
    buttonLabel: props.user != null ? i18n('StartJourney') : i18n('logIn'),
    loginLink:"/login?redirectUrl="+window.location.href,
    isSOP3: async() => {
      let userData = await ADCServices.getUserInfo();
      if (!userData.session.tammUserInfo || userData.session.tammUserInfo.Type!="SOP3") {
        props.SOP3toggleModal(props,true);
        setTimeout(()=>props.SOP3toggleModal(props,false),5000)
        return false;
      } else {
        return true;
      }
    },
  };
};

My Integration work.ts

import { SOP3loginConfig } from 'client/.../sop3login';

const start = async (props: IVariables) => {
  if (props.user) {
    if (await SOP3loginConfig(props).isSOP3()) {
      props.history.push('/adc/card-renewal/customs');
    }
  } else {
    props.history.push(SOP3loginConfig(props).loginLink);
  }
};

Unit testing implmentation of mine work.test.ts

  describe('Start SOP3loginConfig should be called', () => {
    it('Should call the SOP3', async () => {
      props.user = true;
      // const isSOP3Mock = () => {
      //   return true;
      // };
      // let SOP3loginConfig = async (props: any) => {
      //   return true;
      //   // return {
      //   //   isSOP3: isSOP3Mock,
      //   // };
      // };
      let SOP3loginConfig = jest.fn(props => {
        return {
          isSOP3: jest.fn(() => {
            return true;
          }),
        };
      });
      functions.start(props);
      expect(await SOP3loginConfig(props).isSOP3).toHaveBeenCalled();
      expect(props.history.push).toHaveBeenCalled();
    });
  });

Error I am getting

    expect(jest.fn()).toHaveBeenCalled()

    Expected number of calls: >= 1
    Received number of calls:    0

       97 |       });
       98 |       functions.start(props);
    >  99 |       expect(await SOP3loginConfig(props).isSOP3).toHaveBeenCalled();
          |                                                   ^
      100 |       expect(props.history.push).toHaveBeenCalled();
      101 |     });
      102 |   });

All I want to is cover the if (await SOP3loginConfig(props).isSOP3()) part in work.ts.


回答1:


Here is the unit test solution:

sop3login.ts:

import ADCServices from './adc.service';

export interface IVariables {
  user: any;
  history: IHistory;
  i18n(name: string): any;
  SOP3toggleModal(props: IVariables, flag: boolean): void;
}

interface IHistory {
  push(router: string): any;
}

export const SOP3loginConfig = (props: IVariables) => {
  const { i18n } = props;
  return {
    buttonLabel: props.user != null ? i18n('StartJourney') : i18n('logIn'),
    loginLink: '/login?redirectUrl=' + window.location.href,
    isSOP3: async () => {
      const userData = await ADCServices.getUserInfo();
      if (!userData.session.tammUserInfo || userData.session.tammUserInfo.Type !== 'SOP3') {
        props.SOP3toggleModal(props, true);
        setTimeout(() => props.SOP3toggleModal(props, false), 5000);
        return false;
      } else {
        return true;
      }
    },
  };
};

adc.service.ts:

export default class ADCServices {
  public static async getUserInfo() {
    return {
      session: {
        tammUserInfo: {
          Type: 'real type',
        },
      },
    };
  }
}

work.ts:

import { SOP3loginConfig, IVariables } from './sop3login';

const start = async (props: IVariables) => {
  if (props.user) {
    if (await SOP3loginConfig(props).isSOP3()) {
      props.history.push('/adc/card-renewal/customs');
    }
  } else {
    props.history.push(SOP3loginConfig(props).loginLink);
  }
};

export { start };

work.test.ts:

import { start } from './work';
import { SOP3loginConfig, IVariables } from './sop3login';

jest.mock('./sop3login.ts', () => {
  const mObj = {
    isSOP3: jest.fn(),
  };
  return { SOP3loginConfig: jest.fn(() => mObj) };
});

describe('Start SOP3loginConfig should be called', () => {
  it('Should call the SOP3', async () => {
    const mProps: IVariables = {
      user: true,
      history: { push: jest.fn() },
      i18n: jest.fn(),
      SOP3toggleModal: jest.fn(),
    };
    await start(mProps);
    expect(SOP3loginConfig).toBeCalledWith(mProps);
    expect(SOP3loginConfig(mProps).isSOP3).toBeCalledTimes(1);
  });
});

Unit test results with coverage report:

 PASS  src/stackoverflow/59627009/work.test.ts
  Start SOP3loginConfig should be called
    ✓ Should call the SOP3 (7ms)

----------|----------|----------|----------|----------|-------------------|
File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files |    77.78 |       50 |      100 |    71.43 |                   |
 work.ts  |    77.78 |       50 |      100 |    71.43 |               6,9 |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        4.078s, estimated 10s

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



来源:https://stackoverflow.com/questions/59627009/testing-a-function-that-returns-an-object-with-a-function-javascript-jest

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!