enhetstestning - Hur man mockar ett modul med Typescript-namespace?


Det här är funktionen som testas:

import * as firebase from 'firebase';

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

firebase har nedanstående typdefinition:

declare namespace firebase.auth 

och

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

Jag behöver mocka firebase.auth.GoogleAuthProvider(), firebase.auth() och signInWithRedirect-metoderna från firebase.

Men firebase.auth kan vara ett objekt eller en funktion. Vad ska returneras i factory för jest.mock?

Stöder jestjs den här typen av mock eller spy? Tack guys.

Svar #1

Javascript-funktioner är objekt av typen Function. Och till varje objekt kan du tilldela egenskaper så att du kan imitera det som:

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

eller så kan du använda Jests automatiska mocking utan fabriksfunktion:

jest.mock('firebase');

och sedan göra narr av implementeringen

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

Svar #2

Från @Teneff:s svar förstår jag det. Poängen är som @Teneff sa, att TypeScript-namespace är en slags JS-funktion efter kompilering och typborttagning. Efter att ha fått veta detta kan du naturligtvis tilldela egenskaper till JS-funktionen. Här är ett komplett fungerande kodexempel:

index.ts:

import firebase from 'firebase';

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

För enkelhetens skull lägger jag till kommentaren @ts-ignore för att ignorera typkontrollen.

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);
  });
});

Enhetstestresultat:

 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

Källkod: https://github.com/mrdulin/jest-codelab/tree/master/src/mock-ts-namespace

Relaterade artiklar