最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How can I test chained promises in a Jest test? - Stack Overflow

programmeradmin2浏览0评论

Below I have a test for my login actions. I'm mocking a Firebase function and want to test if the signIn/signOut functions are called.

The tests pass. However, I do not see my second console log. Which is this line console.log('store ==>', store);.

it('signIn should call firebase', () => {
  const user = {
    email: '[email protected]',
    password: 'abd123'
  };

  console.log('111');
  return store.dispatch(signIn(user.email, user.password)).then(() => {
    console.log('222'); // Does not reach
    expect(mockFirebaseService).toHaveBeenCalled();
  });
  console.log('333');
});

● login actions › signIn should call Firebase

TypeError: auth.signInWithEmailAndPassword is not a function

Action being tested

// Sign in action
export const signIn = (email, password, redirectUrl = ROUTEPATH_DEFAULT_PAGE) => (dispatch) => {
  dispatch({ type: USER_LOGIN_PENDING });

  return firebase
    .then(auth => auth.signInWithEmailAndPassword(email, password))
    .catch((e) => {
      console.error('actions/Login/signIn', e);
      // Register a new user
      if (e.code === LOGIN_USER_NOT_FOUND) {
        dispatch(push(ROUTEPATH_FORBIDDEN));
        dispatch(toggleNotification(true, e.message, 'error'));
      } else {
        dispatch(displayError(true, e.message));
        setTimeout(() => {
          dispatch(displayError(false, ''));
        }, 5000);
        throw e;
      }
    })
    .then(res => res.getIdToken())
    .then((idToken) => {
      if (!idToken) {
        dispatch(displayError(true, 'Sorry, there was an issue with getting your token.'));
      }

      dispatch(onCheckAuth(email));
      dispatch(push(redirectUrl));
    });
};

Full Test

    import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';

// Login Actions
import {
  // onCheckAuth,
  signIn,
  signOut
} from 'actions';

import {
  // USER_ON_LOGGED_IN,
  USER_ON_LOGGED_OUT
} from 'actionTypes';

// String Constants
// import { LOGIN_USER_NOT_FOUND } from 'copy';

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

// Mock all the exports in the module.
function mockFirebaseService() {
  return new Promise(resolve => resolve(true));
}

// Since "services/firebase" is a dependency on this file that we are testing,
// we need to mock the child dependency.
jest.mock('services/firebase', () => new Promise(resolve => resolve(true)));

describe('login actions', () => {
  let store;

  beforeEach(() => {
    store = mockStore({});
  });

  it('signIn should call firebase', () => {
    const user = {
      email: '[email protected]',
      password: 'abd123'
    };

    console.log('111');
    return store.dispatch(signIn(user.email, user.password)).then(() => {
      console.log('222'); // does not reach
      expect(mockFirebaseService).toHaveBeenCalled();
    });
    console.log('333');
  });

  it('signOut should call firebase', () => {
    console.log('signOut should call firebasew');
    store.dispatch(signOut()).then(() => {
      expect(mockFirebaseService).toHaveBeenCalled();
      console.log('store ==>', store);
      expect(store.getActions()).toEqual({
        type: USER_ON_LOGGED_OUT
      });
    });
    console.log('END');
  });
});

Below I have a test for my login actions. I'm mocking a Firebase function and want to test if the signIn/signOut functions are called.

The tests pass. However, I do not see my second console log. Which is this line console.log('store ==>', store);.

it('signIn should call firebase', () => {
  const user = {
    email: '[email protected]',
    password: 'abd123'
  };

  console.log('111');
  return store.dispatch(signIn(user.email, user.password)).then(() => {
    console.log('222'); // Does not reach
    expect(mockFirebaseService).toHaveBeenCalled();
  });
  console.log('333');
});

● login actions › signIn should call Firebase

TypeError: auth.signInWithEmailAndPassword is not a function

Action being tested

// Sign in action
export const signIn = (email, password, redirectUrl = ROUTEPATH_DEFAULT_PAGE) => (dispatch) => {
  dispatch({ type: USER_LOGIN_PENDING });

  return firebase
    .then(auth => auth.signInWithEmailAndPassword(email, password))
    .catch((e) => {
      console.error('actions/Login/signIn', e);
      // Register a new user
      if (e.code === LOGIN_USER_NOT_FOUND) {
        dispatch(push(ROUTEPATH_FORBIDDEN));
        dispatch(toggleNotification(true, e.message, 'error'));
      } else {
        dispatch(displayError(true, e.message));
        setTimeout(() => {
          dispatch(displayError(false, ''));
        }, 5000);
        throw e;
      }
    })
    .then(res => res.getIdToken())
    .then((idToken) => {
      if (!idToken) {
        dispatch(displayError(true, 'Sorry, there was an issue with getting your token.'));
      }

      dispatch(onCheckAuth(email));
      dispatch(push(redirectUrl));
    });
};

Full Test

    import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';

// Login Actions
import {
  // onCheckAuth,
  signIn,
  signOut
} from 'actions';

import {
  // USER_ON_LOGGED_IN,
  USER_ON_LOGGED_OUT
} from 'actionTypes';

// String Constants
// import { LOGIN_USER_NOT_FOUND } from 'copy';

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

// Mock all the exports in the module.
function mockFirebaseService() {
  return new Promise(resolve => resolve(true));
}

// Since "services/firebase" is a dependency on this file that we are testing,
// we need to mock the child dependency.
jest.mock('services/firebase', () => new Promise(resolve => resolve(true)));

describe('login actions', () => {
  let store;

  beforeEach(() => {
    store = mockStore({});
  });

  it('signIn should call firebase', () => {
    const user = {
      email: '[email protected]',
      password: 'abd123'
    };

    console.log('111');
    return store.dispatch(signIn(user.email, user.password)).then(() => {
      console.log('222'); // does not reach
      expect(mockFirebaseService).toHaveBeenCalled();
    });
    console.log('333');
  });

  it('signOut should call firebase', () => {
    console.log('signOut should call firebasew');
    store.dispatch(signOut()).then(() => {
      expect(mockFirebaseService).toHaveBeenCalled();
      console.log('store ==>', store);
      expect(store.getActions()).toEqual({
        type: USER_ON_LOGGED_OUT
      });
    });
    console.log('END');
  });
});
Share Improve this question edited Oct 13, 2020 at 18:48 Peter Mortensen 31.6k22 gold badges110 silver badges133 bronze badges asked Jan 26, 2018 at 19:31 Leon GabanLeon Gaban 39k122 gold badges349 silver badges550 bronze badges 1
  • You use jest.mock('services/firebase', () => new Promise(resolve => resolve(true))) to mock firebase in your signIn thunk? – Allen Commented Jan 29, 2018 at 16:34
Add a ment  | 

2 Answers 2

Reset to default 6 +150

You have two issues here,

The tests pass however I do not see my 2nd console log. Which is this line console.log('store ==>', store);.

That is because the test is not waiting for the promise to fulfill, so you should return it:

it('signOut should call firebase', () => {
    console.log('signOut should call firebasew');
    return store.dispatch(signOut()).then(() => { // NOTE we return the promise
      expect(mockFirebaseService).toHaveBeenCalled();
      console.log('store ==>', store);
      expect(store.getActions()).toEqual({
        type: USER_ON_LOGGED_OUT
      });
      console.log('END');
    });

  });

You can find examples in the Redux official documentation.

Secondly, your signIn test is failing because you have mocked the wrong firebase:

jest.mock('services/firebase', () => new Promise(resolve => resolve(true)));

That should probably look more like:

jest.mock('services/firebase', () => new Promise(resolve => resolve({
    signInWithEmailAndPassword: () => { return { getIdToken: () => '123'; } }
})));

Login actions › signIn should call firebase

TypeError: auth.signInWithEmailAndPassword is not a function

This tells that your store.dispatch(signIn(user.email, user.password)) fails, thus your second console.log won't go into your then chain, use catch or second callback argument of then instead.

发布评论

评论列表(0)

  1. 暂无评论