Today, I needed to mock up some of the new Firebase 9.0.0 functions to pass the tests that I've been building over the past years. 💣
I've been struggling when mocking up the new onValue()
function. To put things in context, the onValue()
function replaces the old on()
listener. Thus, the old test looked like this:
javascriptimport firebase from '../Functions/Firebase' // I omit imported components for clarity // Basically, the component to test reads the title from Firebase // using an on()listener and renders the text on a <h3></h3> tag it("Acerca -> displays feature", async () => { const data = { feature: { title: "New feature" } } const snapshot = { val: () => data } jest.spyOn(firebase, 'database').mockImplementation(() => ({ ref: jest.fn().mockReturnThis(), on: jest.fn((event, callback) => callback(snapshot)), off: jest.fn().mockReturnThis() })); await act(async () => { render(<Acerca/>, container) }); expect(container.querySelector('h3').textContent).toBe(data.feature.title) })
onValue()
At this point, I needed to replace the whole Firebase library by importing a single onValue()
function.
My first approach was:
javascriptimport { onValue } from './Firebase' it("Acerca -> displays feature", async () => { // This approach doesn't work because the spyOn function requires a module as a first parameter jest.spyOn(/* ... */, 'onValue').mockImplementation(() => /* ... */ ) })
The second approach was to import all the functions on an object called firebase
:
javascriptimport * as firebase from './Firebase' it("Acerca -> displays feature", async () => { // Even if it doesn't look like an optimal solution, it seems feasible, but it doesn't work... // TypeError: cannot redefine property jest.spyOn(firebase, 'onValue').mockImplementation(() => /* ... */ ) })
At this point, I was blocked, but thanks to Chak Shun Yu and slideshowp2 I've arrived at the final solution. The idea here is to mock up the entire module and to modify a specific function:
javascriptimport { onValue } from './Firebase' jest.mock('./Firebase') it("Acerca -> displays feature", async () => { const data = { feature: { title: "New feature" } } const snapshot = { val: () => data } onValue.mockImplementation((ref, callback) => { callback(snapshot) return jest.fn() }) await act(async () => { render(<Acerca/>, container) }); expect(container.querySelector('h3').textContent).toBe(data.feature.title) })
Hi, I'm Erik, an engineer from Barcelona. If you like the post or have any comments, say hi.