简体   繁体   中英

Jest Mocks not registering as called on expect().toBeCalled() when Mocks are called

For the tests in question, I've mocked some callbacks and passed them to the function that I'm testing. I've added console.log inside the mocks just to try and debug what is going on. Those console.log's are printing out in the test log so it appears as though the mocked callbacks are actually being called correctly during the test (See test output below) but when I do an expect(mockedFunction).toBeCalled() that assertion fails. I can't figure out why it's failing since the mocked callbacks are logging out to the console when the test is run. Here's my code:

this is the code I'm trying to test.

import IAccount from './IAccount';
import IAccountManager from './IAccountManager';
import firebase from '../firebase/Firebase';
import { stringHasASymbol } from '../../common/Utility';

export class FirebaseAccountManager implements IAccountManager {

  register(newAccount: IAccount, successCallback: (response: any) => any, errorCallback: (error: any) => any): void {
    console.log("called: FirebaseAccountManager:register()");
    firebase.register(newAccount.email, newAccount.password, newAccount.firstName + " " + newAccount.lastName)
      .then(response => {
        console.log("GOT HERE 1", response)
        successCallback(true);
      })
      .catch(error => {
        console.log("GOT HERE 2", error)
        errorCallback({ code: this.convertRegisterErrorCode(error.code), message: error.message })
      });
  }

  private convertRegisterErrorCode(code: string): string {
    if (code === 'auth/email-already-in-use') {
      return 'email-already-in-use';
    }

    return 'unsupported-error-type: firebase error code = ' + stringHasASymbol;
  }
}

Here is my test:

import { FirebaseAccountManager } from './FirebaseAccountManager';
import IAccount from './IAccount';

jest.mock('firebase/app', () => (
  {
    auth: jest.fn().mockReturnThis(),
    initializeApp: jest.fn(),
    createUserWithEmailAndPassword: jest.fn()
      .mockResolvedValueOnce(true)
      .mockRejectedValueOnce({
        code: 'invalid-email'
      })
  }
));

const mockSuccessCallback = jest.fn((response: any) => {
  console.log("MOCK SUCCESS CALLBACK CALLED", response);
  return 'Success!';
});
const mockErrorCallback = jest.fn((error: any) => {
  console.log("MOCK ERROR CALLBACK CALLED", error);
  return { code: 'invalid-email', message: 'this email is already in use' }
});

afterEach(() => {
  jest.clearAllMocks();
});

describe('test', () => {
  test('Successful Registration', () => {
    console.log("START Successful Registration")
    const newAccount: IAccount = { firstName: 'asdf', lastName: 'asdf', email: 'asdf@adf.com', password: 'qwer', phoneNumber: '', workStatus: '', city: '', postalCode: '', country: '' }

    const fam = new FirebaseAccountManager();
    fam.register(newAccount, mockSuccessCallback, mockErrorCallback);
    console.log(mockSuccessCallback.mock.calls.length)
    expect(mockSuccessCallback).toBeCalled();
    expect(mockErrorCallback).not.toBeCalled();
    console.log("DONE Successful Registration")
  });

  test('Failed Registration', () => {
    console.log("START Failed Registration")
    const newAccount: IAccount = { firstName: 'asdf', lastName: 'asdf', email: 'asdf@adf.com', password: 'qwer', phoneNumber: '', workStatus: '', city: '', postalCode: '', country: '' }

    const fam = new FirebaseAccountManager();
    fam.register(newAccount, mockSuccessCallback, mockErrorCallback);
    expect(mockSuccessCallback).not.toBeCalled();
    expect(mockErrorCallback).toBeCalled();
    console.log("DONE Failed Registration")
  });

});

both fail even though the callbacks are invoked. Here's the test output:

 FAIL  src/middleware/Account/FirebaseAccountManager.test.ts
  test
    ✕ Successful Registration (7ms)
    ✕ Failed Registration (3ms)

  ● test › Successful Registration

    expect(jest.fn()).toBeCalled()

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

      35 |     fam.register(newAccount, mockSuccessCallback, mockErrorCallback);
      36 |     console.log(mockSuccessCallback.mock.calls.length)
    > 37 |     expect(mockSuccessCallback).toBeCalled();
         |                                 ^
      38 |     expect(mockErrorCallback).not.toBeCalled();
      39 |     console.log("DONE Successful Registration")
      40 |   });

      at Object.<anonymous> (src/middleware/Account/FirebaseAccountManager.test.ts:37:33)

  ● test › Failed Registration

    expect(jest.fn()).toBeCalled()

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

      47 |     fam.register(newAccount, mockSuccessCallback, mockErrorCallback);
      48 |     expect(mockSuccessCallback).not.toBeCalled();
    > 49 |     expect(mockErrorCallback).toBeCalled();
         |                               ^
      50 |     console.log("DONE Failed Registration")
      51 |   });
      52 | 

      at Object.<anonymous> (src/middleware/Account/FirebaseAccountManager.test.ts:49:31)

  console.log src/middleware/Account/FirebaseAccountManager.test.ts:31
    START Successful Registration

  console.log src/middleware/Account/FirebaseAccountManager.ts:8
    called: FirebaseAccountManager:register()

  console.log src/middleware/Account/FirebaseAccountManager.test.ts:36
    0

  console.log src/middleware/Account/FirebaseAccountManager.ts:11
    GOT HERE 1 true

  console.log src/middleware/Account/FirebaseAccountManager.test.ts:17
    MOCK SUCCESS CALLBACK CALLED true

  console.log src/middleware/Account/FirebaseAccountManager.test.ts:43
    START Failed Registration

  console.log src/middleware/Account/FirebaseAccountManager.ts:8
    called: FirebaseAccountManager:register()

  console.log src/middleware/Account/FirebaseAccountManager.ts:15
    GOT HERE 2 { code: 'invalid-email' }

  console.log src/middleware/Account/FirebaseAccountManager.test.ts:21
    MOCK ERROR CALLBACK CALLED {
      code: 'unsupported-error-type: firebase error code = invalid-email',
      message: undefined
    }

Test Suites: 1 failed, 1 total
Tests:       2 failed, 2 total
Snapshots:   0 total
Time:        0.967s, estimated 1s
Ran all test suites matching /Fire/i.

Watch Usage: Press w to show more.

Test Results Screenshot

I solved this. The issue was that the register function in FirebaseAccountManager was handling a promise but was not async. Once I added async to the function and awaited it in the test the tests passed. I think the test was asserting that the callback had been called prior to the promise resolving or rejecting it. Updated code examples as follows:

  async register(newAccount: IAccount, successCallback: (response: any) => any, errorCallback: (error: any) => any): Promise<any> {
    console.log("called: FirebaseAccountManager:register()");
    await firebase.register(newAccount.email, newAccount.password, newAccount.firstName + " " + newAccount.lastName)
      .then(response => {
        console.log("GOT HERE 1", response)
        successCallback(true);
      })
      .catch(error => {
        console.log("GOT HERE 2", error)
        errorCallback({ code: this.convertRegisterErrorCode(error.code), message: error.message })
      });
  }

And here's the changed tests that now pass.

  test('Successful Registration', async () => {
    console.log("START Successful Registration")
    const newAccount: IAccount = { firstName: 'asdf', lastName: 'asdf', email: 'asdf@adf.com', password: 'qwer', phoneNumber: '', workStatus: '', city: '', postalCode: '', country: '' }

    const fam = new FirebaseAccountManager();
    await fam.register(newAccount, mockSuccessCallback, mockErrorCallback);
    expect(mockSuccessCallback).toBeCalled();
    expect(mockErrorCallback).not.toBeCalled();
    console.log("DONE Successful Registration")
  });

  test('Failed Registration', async () => {
    console.log("START Failed Registration")
    const newAccount: IAccount = { firstName: 'asdf', lastName: 'asdf', email: 'asdf@adf.com', password: 'qwer', phoneNumber: '', workStatus: '', city: '', postalCode: '', country: '' }

    const fam = new FirebaseAccountManager();
    await fam.register(newAccount, mockSuccessCallback, mockErrorCallback);
    expect(mockSuccessCallback).not.toBeCalled();
    expect(mockErrorCallback).toBeCalled();
    console.log("DONE Failed Registration")
  });

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