firebase-mock icon indicating copy to clipboard operation
firebase-mock copied to clipboard

Best method for "clearing/resetting" firestore between tests?

Open joelclimbsthings opened this issue 7 years ago • 9 comments

Do I just need to cycle through and call .delete() for all documents between tests, or is there a better way?

I'm using Jest as the test runner.

joelclimbsthings avatar Nov 19 '18 19:11 joelclimbsthings

It looks like this repo is no longer maintained?

joelclimbsthings avatar Dec 12 '18 15:12 joelclimbsthings

Just reset the firestore mock using beforeEach. See https://github.com/soumak77/firebase-mock/blob/master/tutorials/integration/setup.md for setup.

beforeEach(() => {
    mockfirestore = new firebasemock.MockFirestore();
})

Hope this helps :)

Jank1310 avatar Jan 25 '19 19:01 Jank1310

@Jank1310, that doesn't work for Jest tests, though. I have this at the top of my tests:

jest.mock('firebaseConfig', () => {
  const firebasemock = require('firebase-mock');
  const mockauth = new firebasemock.MockAuthentication();
  const mockfirestore = new firebasemock.MockFirestore();
  return new firebasemock.MockFirebaseSdk(
    null, // RTDB
    () => mockauth,
    () => mockfirestore
  );
});

It has to be outside of the beforeEach block to work, so resetting it that way won't work. It would be nice to have some form of cleanup method you could call to quickly clear the data.

p12y avatar Mar 25 '19 10:03 p12y

@p12y It works. I'm using it every day :) Maybe I'm missing something, do you see any problems with the following approach?

I pass the admin sdk (and other dependencies) into the functions from the index.js.

Sample Function

const someFunction = (adminSdk, dep1, dep2) => async () => {
 // do something with the sdk and other dependencies
}

Sample Test

const firebasemock = require("firebase-mock");

// mock what you need
let mockauth = new firebasemock.MockAuthentication();
let mockfirestore = new firebasemock.MockFirestore();
let mocksdk = firebasemock.MockFirebaseSdk(
  null,
  () => mockauth,
  () => mockfirestore
);
mocksdk.initializeApp();

describe("some-set-of-tests", () => {
  beforeEach(() => {
    // reset components
    mockfirestore = new firebasemock.MockFirestore();
    mockfirestore.autoFlush();
    mockauth = new firebasemock.MockAuthentication();
    mockauth.autoFlush();
  });

  it('should do something', async () => {
    const fn = someFunction(adminSdk, dep1, dep2);
    const result = await fn();
    ....
  })

Jank1310 avatar Mar 26 '19 08:03 Jank1310

@Jank1310 I'm doing integration testing with React, so I need to call jest.mock to mock out the module in my components. I found the solution, which is a variation of what you are doing by exporting a reset function and calling it in the afterEach hook. E.g.

// Outside the test block
jest.mock('firebaseConfig', () => {
  const firebasemock = require('firebase-mock');
  let mockauth = new firebasemock.MockAuthentication();
  let mockfirestore = new firebasemock.MockFirestore();

  function reset() {
    mockauth = new firebasemock.MockAuthentication();
    mockfirestore = new firebasemock.MockFirestore();
  }

  const sdk = new firebasemock.MockFirebaseSdk(
    null, // RTDB
    () => mockauth,
    () => mockfirestore
  );

  return {
    reset,
    ...sdk,
  }
});

// Inside the test block
 afterEach(() => {
   firebase.reset();
 });

Cheers for the help!

p12y avatar Mar 28 '19 10:03 p12y

@p12y I have same issue and I've tried your solution. But it dosen't work.

Below is the simplified code. is there something wrong?

mockTarget.js

export const counter = { count: 0 }
// for enable import { increment } from './mockTarget'
export const increment = () => {}

sample.test.js

import { counter, increment } from './mockTarget'

jest.mock('./mockTarget', () => {
  let count = 0
  return {
    counter: count,
    increment: () => { 
      count++ 
      return count
    }
  }
})


it("simple test", () => {
  console.log(counter) // 0
  const result = increment()
  console.log(result) // 1
  console.log(counter) // if incremnet function work, expected 1 but actual 0
  expect(true).toBe(true)
})


Ryomasao avatar Nov 19 '19 09:11 Ryomasao

@Ryomasao I'm not sure how that's the same problem? Either way, the reason that's not working is because primitives are passed by value. What you want to do is increment the value of counter, not count.

jest.mock('./mockTarget', () => {
  return {
    counter: 0,
    increment: () => { 
      this.counter++
      return this.counter
    }
  }
})

p12y avatar Nov 19 '19 11:11 p12y

@p12y Thank you for reply! I understood perfectly! Thank you!

wrong

jest.mock('../firebase',() => {
  const firebaseMock =  require('firebase-mock')
  const mockfirestore = new firebaseMock.MockFirestore()
  mockfirestore.autoFlush()
  return { 
    db:mockfirestore, 
    reset: () => {      
      // This will not change the db reference
      mockfirestore = new firebaseMock.MockFirestore()
      mockfirestore.autoFlush()
  } }
})

success

jest.mock('../firebase',() => {
  const firebaseMock =  require('firebase-mock')
  const mockfirestore = new firebaseMock.MockFirestore()
  mockfirestore.autoFlush()
  return { 
    db:mockfirestore, 
    reset: function(this: any) {
      const mockfirestore = new firebaseMock.MockFirestore()
      mockfirestore.autoFlush()
      this.db = mockfirestore
  } }
})

Ryomasao avatar Nov 20 '19 01:11 Ryomasao

Been trying to make this "reset firestore" function work like you did but it's not clearing the firestore database after running reset() in my beforeEach or inside my tests.

jest.mock('../init', () => {
  const firebasemock = require('firebase-mock');

  let mockauth = new firebasemock.MockAuthentication();
  let mockstorage = new firebasemock.MockStorage();
  let mockfirestore = new firebasemock.MockFirestore();
  mockfirestore.autoFlush();

  return {
    reset: function() {
      const mockAut = new firebasemock.MockAuthentication();
      const mockStor = new firebasemock.MockStorage();
      const mockFire = new firebasemock.MockFirestore();
      mockFire.autoFlush();

      this.auth = mockAut;
      this.storage = mockStor;
      this.firestore = mockFire;
    },
    firestore: mockfirestore,
    auth: mockauth,
    storage: mockstorage,
    functions: jest.fn()
  };
});

Sorry for commenting in an old thread but I couldn't find any resource to get this to work, maybe we have a function to reset the database now ?

dev-andremonteiro avatar Jan 12 '21 22:01 dev-andremonteiro