title: How can I mock functions in a imported module using Jest?
body: <p>I have a module called authProvider.js which I want to mock when I'm testing one of my functions in api.js.
  I have set <em>"automock": true</em> in my jest config.</p>
  
  <p>This is my structure</p>
  
  <pre><code>src
   |-auth
   |  |-__mocks__
   |  |  |-authProvider.js
   |  |-authProvider.js
   |-utils
      |-api.js
      |-api.test.js
  </code></pre>
  
  <p>This is what I have tried so far but only having success with the first test case. I'm not sure how to set up the mocking in the second test case...</p>
  
  <p>api.test.js</p>
  
  <pre><code>import { mockAuthProvider } from "../auth/__mocks__/authProvider";
  import { getDefaultHeaders, getValueIndexByColumnName } from './api';
  
  describe('API utils', () =&gt; {
      describe('getDefaultHeaders', () =&gt; {
          it('Not authenticated', async () =&gt; {
              expect(await getDefaultHeaders()).toEqual({
                  'Content-Type': 'application/json'
              });
          });
  
          it('Authenticated', async () =&gt; {
              mockAuthProvider.getAccount.mockImplementationOnce(() =&gt;
                  Promise.resolve({user: 'test'})
              );
  
              const headers = await getDefaultHeaders();
  
              expect(mockAuthProvider.getAccount).toBeCalled();
              expect(headers).toEqual({
                  Authorization: 'Bearer abc123',
                  'Content-Type': 'application/json'
              });
          });
      });
  });
  </code></pre>
  
  <p>api.js</p>
  
  <pre><code>import { authProvider } from '../auth/authProvider';
  import settings from '../settings';
  
  export async function getDefaultHeaders() {
      const account = await authProvider.getAccount();
      const authenticationParameters = {
          scopes: ['api://' + settings.AD_CLIENT_ID + '/login'],
          redirectUri: window.location.origin + '/auth.html'
      };
      let token;
  
      if (account) {
          try {
              token = await authProvider.acquireTokenSilent(authenticationParameters);
          } catch (error) {
              token = await authProvider.acquireTokenPopup(authenticationParameters);
          }
      }
  
      if (token) {
          return {
              Authorization: `Bearer ${token.accessToken}`,
              'Content-Type': 'application/json'
          }
      }
      return {
          'Content-Type': 'application/json'
      }
  }
  </code></pre>
  
  <p>__ mocks __/authProvider.js</p>
  
  <pre><code>const mockAuthProvider = {
      getAccount: jest.fn(),
      acquireTokenSilent: jest.fn(),
      acquireTokenPopup: jest.fn()
  };
  
  module.exports = {
      mockAuthProvider
  };
  </code></pre>
  
  <p>Error message</p>
  
  <pre><code>Expected number of calls: &gt;= 1
  Received number of calls:    0
  
    18 |             const headers = await getDefaultHeaders();
    19 |
  &gt; 20 |             expect(mockAuthProvider.getAccount).toBeCalled();
       |                                                 ^
  </code></pre>
  
  <p><strong>UPDATE</strong></p>
  
  <p>I added a file to mock the whole module that exports the auth provider, but still not the best way to solve it I think. I'm having difficulties using it in multiple test cases since I need to specify the return values in a specific order.</p>
  
  <p>Is there a better way to solve this issue?</p>
  
  <p>__ mocks __/react-aad-msal.js</p>
  
  <pre><code>import React from 'react';
  
  const errorObj = {
      message: 'Some error'
  };
  
  export const mockGetAccount = jest.fn()
      .mockReturnValueOnce(null) // Not authenticated
      .mockReturnValueOnce({user: 'test'}) // Authenticated silent
      .mockReturnValueOnce({user: 'test'}); // Authenticated popup
  export const mockAcquireTokenSilent = jest.fn()
      .mockReturnValueOnce({accessToken: 'abc123'}) // Authenticated silent
      .mockRejectedValueOnce(errorObj); // Authenticated popup
  export const mockAcquireTokenPopup = jest.fn()
      .mockReturnValueOnce({accessToken: 'abc123'}); // Authenticated popup
  
  export const MsalAuthProvider = jest.fn(() =&gt; ({
      getAccount: mockGetAccount,
      acquireTokenSilent: mockAcquireTokenSilent,
      acquireTokenPopup: mockAcquireTokenPopup
  }));
  
  export const AuthenticationState = {
      Authenticated: 'Authenticated',
      Unauthenticated: 'Unauthenticated'
  };
  
  export const LoginType = {
      Popup: 'popup'
  };
  
  export const AuthenticationActions = {
      Initializing: 'Initializing',
      Initialized: 'Initialized',
      AcquiredIdTokenSuccess: 'AcquiredIdTokenSuccess',
      AcquiredAccessTokenSuccess: 'AcquiredAccessTokenSuccess',
      AcquiredAccessTokenError: 'AcquiredAccessTokenError',
      LoginSuccess: 'LoginSuccess',
      LoginError: 'LoginError',
      AcquiredIdTokenError: 'AcquiredIdTokenError',
      LogoutSucc: 'LogoutSucc',
      AuthenticatedStateChanged: 'AuthenticatedStateChanged'
  };
  
  export const AzureAD = ({children}) =&gt; &lt;div&gt;{children}&lt;/div&gt;;
  </code></pre>
  
  <p>The new api.test.js looks like this, note that the order of the tests now is important since the return values from the mock are in a fixed order.</p>
  
  <pre><code>import { getDefaultHeaders, axiosCreate, getValueIndexByColumnName } from './api';
  
  describe('API utils', () =&gt; {
      describe('getDefaultHeaders', () =&gt; {
          it('Not authenticated', async () =&gt; {
              const headers = await getDefaultHeaders();
  
              expect(headers).toEqual({
                  'Content-Type': 'application/json'
              });
          });
  
          it('Authenticated silent', async () =&gt; {
              const headers = await getDefaultHeaders();
  
              expect(headers).toEqual({
                  Authorization: 'Bearer abc123',
                  'Content-Type': 'application/json'
              });
          });
  
          it('Authenticated popup', async () =&gt; {
              const headers = await getDefaultHeaders();
  
              expect(headers).toEqual({
                  Authorization: 'Bearer abc123',
                  'Content-Type': 'application/json'
              });
          });
      });
  
      describe('axiosCreate', () =&gt; {
          it('Create axios API base', () =&gt; {
              expect(axiosCreate()).toBeTruthy();
          });
      });
  
      describe('getValueIndexByColumnName', () =&gt; {
          it('Invalid input data', () =&gt; {
              expect(getValueIndexByColumnName([], null)).toEqual(null);
              expect(getValueIndexByColumnName(['column1'], null)).toEqual(-1);
          });
  
          it('Valid input data', () =&gt; {
              expect(getValueIndexByColumnName(['column1'], 'column')).toEqual(-1);
              expect(getValueIndexByColumnName(['column1'], 'column1')).toEqual(0);
              expect(getValueIndexByColumnName(['column1', 'column2', 'column3'], 'column2')).toEqual(1);
          });
      });
  });
  </code></pre>