Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

exposing getters breaks mocks with es6 imports #160

Closed
phra opened this issue Dec 15, 2017 · 3 comments
Closed

exposing getters breaks mocks with es6 imports #160

phra opened this issue Dec 15, 2017 · 3 comments

Comments

@phra
Copy link

phra commented Dec 15, 2017

[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)
@google-oss-bot
Copy link

Hmmm this issue does not seem to follow the issue template. Make sure you provide all the required information.

@phra
Copy link
Author

phra commented Dec 15, 2017

a potential solution is cited here: https://stackoverflow.com/a/33169197

@hiranya911
Copy link
Contributor

spyOnProperty() is now the recommended way to mock/stub Admin SDK namespace methods when using Jasmine. There are equivalent mocking techniques for Sinon. See #122 for a related discussion and code samples.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants