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
