Skip to content

exposing getters breaks mocks with es6 imports #160

@phra

Description

@phra

[REQUIRED] Step 2: Describe your environment

  • Operating System version: linux
  • Firebase SDK version: 3.16.0
  • Library version: 5.5.1
  • Firebase Product: auth, database

[REQUIRED] Step 3: Describe the problem

i use this technique to mock dependencies imported via es6 imports without having a dependency injection mechanism.

#106 introduces getters for main modules, effectively breaking the cited technique.

Relevant Code:

source.ts

import { auth, credential, database, firestore, initializeApp, ServiceAccount } from 'firebase-admin'

source.spec.ts

import * as admin from 'firebase-admin'

describe('App', async () => {
  beforeEach(async () => {
    spyOn(admin, 'initializeApp')

    spyOn(admin, 'auth' as any).and.returnValue({
      initializeApp: jest.fn(),
      verifyIdToken: jest.fn().mockReturnValue(Promise.resolve({ uid: 'UID' })),
      getUser: jest.fn().mockReturnValue(Promise.resolve({
        uid: 'UID',
        displayName: 'displayName',
        email: 'email',
      })),
    })

    spyOn(functions, 'config' as any).and.returnValue({
      firebase: {},
      sendgrid: {
        apikey: 'apikey',
      },
    })

    spyOn(mail, 'send').and.returnValue(Promise.resolve(void 0))
  })

  describe('/hello-world request', async () => {
    // tslint:disable-next-line:no-empty
    beforeEach(async () => { })

    // tslint:disable-next-line:no-empty
    afterEach(async () => { })

    it('should fail if anonymous user', async () => {
      const [err, res] = await to(anonymousRequest((FUNCTIONS as any).default, '/hello-world'))
      expect(err).toBeFalsy()
      expect(res.status).toBe(403)
      expect(res.text).toBe('Unauthorized')
    })

    it('works', async () => {
      const [err, res] = await to(request((FUNCTIONS as any).default, '/hello-world'))
      expect(err).toBeFalsy()
      expect(res.status).toBe(200)
      expect(res.text).toBe('"Hello from Firebase!"')
    })
  })

Result

running tests results in this errors:

  ● App › /hello-world request › should fail if anonymous user

    TypeError: Cannot set property auth of #<FirebaseNamespace> which has only a getter
      
      at SpyRegistry.spyOn (node_modules/jest-jasmine2/build/jasmine/spy_registry.js:127:21)
      at Object.<anonymous> (__tests__/index.spec.ts:44:5)
          at Generator.next (<anonymous>)
      at __tests__/index.spec.ts:7:71
          at new Promise (<anonymous>)
      at Object.<anonymous>.__awaiter (__tests__/index.spec.ts:3:12)
      at Object.beforeEach (__tests__/index.spec.ts:41:25)

  ● App › /hello-world request › should fail if anonymous user

    Firebase config variables are not available. Please use the latest version of the Firebase CLI to deploy this function.
      
      at init (node_modules/firebase-functions/lib/config.js:51:15)
      at Object.config (node_modules/firebase-functions/lib/config.js:29:9)
      at Timeout.Object.<anonymous>.setTimeout [as _onTimeout] (index.ts:58:8)
      at ontimeout (timers.js:475:11)
      at tryOnTimeout (timers.js:310:5)
      at Timer.listOnTimeout (timers.js:270:5)

  ● App › /hello-world request › works

    TypeError: Cannot set property auth of #<FirebaseNamespace> which has only a getter
      
      at SpyRegistry.spyOn (node_modules/jest-jasmine2/build/jasmine/spy_registry.js:127:21)
      at Object.<anonymous> (__tests__/index.spec.ts:44:5)
          at Generator.next (<anonymous>)
      at __tests__/index.spec.ts:7:71
          at new Promise (<anonymous>)
      at Object.<anonymous>.__awaiter (__tests__/index.spec.ts:3:12)
      at Object.beforeEach (__tests__/index.spec.ts:41:25)

  ● App › /hello-world request › works

    expect(received).toBe(expected)
    
    Expected value to be (using ===):
      200
    Received:
      500
      
      at Object.<anonymous> (__tests__/index.spec.ts:81:26)
          at Generator.next (<anonymous>)
      at fulfilled (__tests__/index.spec.ts:4:56)
          at <anonymous>
      at process._tickCallback (internal/process/next_tick.js:188:7)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions