How to mock a module with typescript namespace?

最后都变了- 提交于 2021-01-29 02:51:55

问题


This is the function under test:

import * as firebase from 'firebase';

function signInWithGoogle() {
  var provider = new firebase.auth.GoogleAuthProvider();
  firebase.auth().signInWithRedirect(provider);
}

firebase has below type definition:

declare namespace firebase.auth 

and

function auth(app?: firebase.app.App): firebase.auth.Auth;
jest.mock('firebase', () => {
  // Don't know how to mock, what should be returned?  
})

I need mock firebase.auth.GoogleAuthProvider(), firebase.auth() and signInWithRedirect methods of firebase.

But the firebase.auth can be an object or a function. What should be returned in the factory of jest.mock?

Does jestjs support this kind of mock or spy? Thanks guys.


回答1:


Javascript functions are objects of type Function. And to every object you can assign properties so you can mock it as:

jest.mock('firebase', () => {
  const auth = jest.fn();
  auth.GoogleAuthProvider = jest.fn();
  auth.Auth = jest.fn();
  return { auth };
});

or you can use Jest's auto-mocking without factory function:

jest.mock('firebase');

and then mock the implementation

// based on your question (not tested)
firebase.auth.mockImplementation(() => new firebase.auth.Auth())



回答2:


From @Teneff's answer, I figure it out. The point is like @Teneff said, typescript namespace is some kind of a JS function after compiling and type erasure. After knowing this, of course, you can assign properties to JS function. Here is the completed working code example:

index.ts:

import firebase from 'firebase';

export function signInWithgoogle() {
  const provider = new firebase.auth.GoogleAuthProvider();
  firebase.auth().signInWithRedirect(provider);
}

For simple, I add @ts-ignore comment in order to ignore the type check.

index.spec.ts:

import { signInWithgoogle } from './';
import firebase from 'firebase';

jest.mock('firebase', () => {
  const auth = jest.fn();
  const mAuth = { signInWithRedirect: jest.fn() };
  // @ts-ignore
  auth.GoogleAuthProvider = jest.fn();
  // @ts-ignore
  auth.Auth = jest.fn(() => mAuth);
  return { auth };
});

describe('signInWithgoogle', () => {
  it('should mock firebase with typescript namespace', () => {
    // @ts-ignore
    firebase.auth.mockImplementation(() => new firebase.auth.Auth());
    signInWithgoogle();
    expect(firebase.auth.GoogleAuthProvider).toBeCalledTimes(1);
    expect(firebase.auth).toBeCalledTimes(1);
    expect(firebase.auth().signInWithRedirect).toBeCalledTimes(1);
  });
});

Unit test result:

 PASS  src/mock-ts-namespace/index.spec.ts
  signInWithgoogle
    ✓ should mock firebase with typescript namespace (7ms)

----------|----------|----------|----------|----------|-------------------|
File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files |      100 |      100 |      100 |      100 |                   |
 index.ts |      100 |      100 |      100 |      100 |                   |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        4.964s

Source code: https://github.com/mrdulin/jest-codelab/tree/master/src/mock-ts-namespace



来源:https://stackoverflow.com/questions/58873758/how-to-mock-a-module-with-typescript-namespace

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