使用Jest测试Firebase RealtimeDatabase

时间:2018-11-10 12:39:32

标签: javascript firebase unit-testing firebase-realtime-database jestjs

我的目的仅仅是测试一个功能。我无法弄清楚如何正确模拟Firebase。我尝试保留来自Jest docs的axios模拟示例。我有以下代码:

MusicService.js

import { initializeApp } from "firebase/app";
import "firebase/database";

const firebase = initializeApp({
  apiKey: "<API_KEY>",
  authDomain: "<PROJECT_ID>.firebaseapp.com",
  databaseURL: "https://<DATABASE_NAME>.firebaseio.com",
  projectId: "<PROJECT_ID>",
  storageBucket: "<BUCKET>.appspot.com",
  messagingSenderId: "<SENDER_ID>",
});

export class MusicService {
  static getAlbums() {
    return firebase.database().ref("albums").once("value")
    .then(snapshot => Object.values(snapshot.val()));
  }
}

MusicService.test.js

import firebase from 'firebase/app';
import 'firebase/database';
import { MusicService } from './MusicService';

jest.mock('firebase/app');
jest.mock('firebase/database');

test("test", () => {
  firebase.initializeApp.mockImplementation(() => {
    database: jest.fn(() => {
      return {
        ref: jest.fn()
      }
    })
  });

  MusicService.getAlbums();
});

问题是出现以下错误: enter image description here

我尝试模拟firebase.database。

test("test", () => {
  firebase.mockImplementation(() => {
    return {
      database: {

      }
    }
  });
  MusicService.getAlbums();
});

但是在这种情况下,我得到的错误提示:

  

TypeError:_app.default.mockImplementation不是函数。

我不希望给出工作示例,但是请您告诉我,我到底应该嘲笑什么?整个firebase库或我的函数开始的部分-return firebase.database()

2 个答案:

答案 0 :(得分:1)

我知道了。我应该只模拟那些要测试的功能所依赖的模块。例如,我要测试getAlbums函数。它使用从initializeApp中的firebase/app模块导入的MusicService.js函数。因此,在调用initializeApp函数时,它应返回一个包含database函数的对象,而该对象又将返回一个具有refonce函数的对象。代码:

MusicService.test.js

import { MusicService } from "./FirebaseService";

jest.mock("firebase/app", () => {
  const data = { name: "unnamed" };
  const snapshot = { val: () => data };
  return {
    initializeApp: jest.fn().mockReturnValue({
      database: jest.fn().mockReturnValue({
        ref: jest.fn().mockReturnThis(),
        once: jest.fn(() => Promise.resolve(snapshot))
      })
    })
  };
});

test("getAlbums function returns an array", async () => {
  const data = await MusicService.getAlbums();
  expect(data.constructor).toEqual(Array);
});

答案 1 :(得分:0)

这是我当前对firebase.js的模拟实现。 对我来说一切正常。

const firebase = jest.genMockFromModule('firebase');

firebase.initializeApp = jest.fn();

const data = { name: 'data' };
const snapshot = { val: () => data, exportVal: () => data, exists: jest.fn(() => true) };

firebase.database = jest.fn().mockReturnValue({
  ref: jest.fn().mockReturnThis(),
  on: jest.fn((eventType, callback) => callback(snapshot)),
  update: jest.fn(() => Promise.resolve(snapshot)),
  remove: jest.fn(() => Promise.resolve()),
  once: jest.fn(() => Promise.resolve(snapshot)),
});

firebase.auth = jest.fn().mockReturnValue({
  currentUser: true,
  signOut() {
    return Promise.resolve();
  },
  signInWithEmailAndPassword(email, password) {
    return new Promise((resolve, reject) => {
      if (password === 'sign' || password === 'key') {
        resolve({ name: 'user' });
      }
      reject(Error('sign in error '));
    });
  },
  createUserWithEmailAndPassword(email, password) {
    return new Promise((resolve, reject) => {
      if (password === 'create' || password === 'key') {
        resolve({ name: 'createUser' });
      }
      reject(Error('create user error '));
    });
  },
});

export default firebase;