模拟 firebase 模块后模拟 firebase auth 方法的实现

Phi*_*hil 8 javascript unit-testing typescript jestjs firebase-authentication

我想更改内部方法的实现jest.mock,以便我可以检查我的应用程序对不同边缘情况的反应,所以我这样做了,但是打字稿不允许我模拟firebase.auth().currentUser方法...我在下面显示我的代码和错误

\n\n

应用程序.js

\n\n
import firebase from 'firebase/app'\nimport 'firebase/auth'\nimport './Init'\n\nconst App = {\ngetLoggedInUser: () => {\n    const currentUser = firebase.auth().currentUser\n    if (currentUser) {\n      return {\n        email: firebase.auth().currentUser.email,\n        userId: firebase.auth().currentUser.uid,\n        isEmailVerified: firebase.auth().currentUser.emailVerified\n      }\n    } else {\n      return undefined\n    }\n  },\n  isAuthenticated: () => {\n    return !!((App.getLoggedInUser() && App.getLoggedInUser().isEmailVerified === true))\n  },\n}\nexport default App\n
Run Code Online (Sandbox Code Playgroud)\n\n

应用程序规范

\n\n
import myAuthenticationPlugin from 'authenticationPlugin/App'\nimport firebase from 'firebase/app'\n\njest.mock('firebase/app', () => {\n  const userCredentialMock = {\n    user: {\n      sendEmailVerification: jest.fn()\n    }\n  }\n  return {\n    auth: jest.fn().mockReturnThis(),\n    currentUser: {\n      email: 'test',\n      uid: '123',\n      emailVerified: true\n    },\n    signInWithEmailAndPassword: jest.fn(),\n    createUserWithEmailAndPassword: jest.fn(() => userCredentialMock),\n    sendPasswordResetEmail: jest.fn(),\n    signOut: jest.fn(),\n    onAuthStateChanged: jest.fn(),\n    initializeApp: jest.fn()\n  }\n})\n\n  describe('Test for isAuthenticated ()', () => {\n    afterEach(() => {\n      jest.resetAllMocks()\n    })\n    it('The API should return a boolean value telling us, If the user is authenticated to access the resources or not', () => {\n      expect(myAuthenticationPlugin.isAuthenticated()).toBe(true)\n    })\n\n    firebase.auth().currentUser = jest.fn(() => {\n      return {\n        email: 'test',\n        uid: '123',\n        emailVerified: false\n      }\n    })\n\n    it('Check false', () => {\n      expect(myAuthenticationPlugin.isAuthenticated()).toBe(false)\n    })\n  })\n
Run Code Online (Sandbox Code Playgroud)\n\n

我得到的错误

\n\n
 FAIL  tests/unit/App.spec.ts\n  \xe2\x97\x8f Test suite failed to run\n\n    TypeScript diagnostics (customize using `[jest-config].globals.ts-jest.diagnostics` option):\n    tests/unit/App.spec.ts:44:5 - error TS2740: Type 'Mock<{ email: string; uid: string; emailVerified: boolean; }, []>' is missing the following properties from type 'User': delete, emailVerified, getIdTokenResult, getIdToken, and 31 more.\n\n    44     firebase.auth().currentUser = jest.fn(() => {\n           ~~~~~~~~~~~~~~~~~~~~~~~~~~~\n
Run Code Online (Sandbox Code Playgroud)\n\n

我现在很困惑如何继续测试我的应用程序的不同边缘情况,有什么办法可以解决这个问题吗?

\n

sli*_*wp2 7

您需要模拟firebase.auth方法及其返回值作为currentUser.

\n\n

例如\n app.ts

\n\n
import firebase from \'firebase/app\';\n\nconst App = {\n  getLoggedInUser: () => {\n    const currentUser = firebase.auth().currentUser;\n    if (currentUser) {\n      return {\n        email: currentUser.email,\n        userId: currentUser.uid,\n        isEmailVerified: currentUser.emailVerified,\n      };\n    } else {\n      return undefined;\n    }\n  },\n  isAuthenticated: () => {\n    return !!(App.getLoggedInUser() && App.getLoggedInUser()!.isEmailVerified === true);\n  },\n};\nexport default App;\n
Run Code Online (Sandbox Code Playgroud)\n\n

app.test.ts:

\n\n
import App from \'./app\';\nimport firebase from \'firebase/app\';\n\njest.mock(\'firebase/app\', () => {\n  return {\n    auth: jest.fn(),\n  };\n});\n\ndescribe(\'61408137\', () => {\n  it(\'should return user\', () => {\n    (firebase.auth as jest.Mocked<any>).mockReturnValueOnce({\n      currentUser: { email: \'example@gmail.com\', uid: 1, emailVerified: true },\n    });\n    const actual = App.getLoggedInUser();\n    expect(actual).toEqual({\n      email: \'example@gmail.com\',\n      userId: 1,\n      isEmailVerified: true,\n    });\n  });\n\n  it(\'should return undefined\', () => {\n    (firebase.auth as jest.Mocked<any>).mockReturnValueOnce({});\n    const actual = App.getLoggedInUser();\n    expect(actual).toBeUndefined();\n  });\n});\n
Run Code Online (Sandbox Code Playgroud)\n\n

带有覆盖率报告的单元测试结果:

\n\n
 PASS  stackoverflow/61408137/app.test.ts (9.822s)\n  61408137\n    \xe2\x9c\x93 should return user (3ms)\n    \xe2\x9c\x93 should return undefined (1ms)\n\n----------|---------|----------|---------|---------|-------------------\nFile      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s \n----------|---------|----------|---------|---------|-------------------\nAll files |    87.5 |       50 |      50 |    87.5 |                   \n app.ts   |    87.5 |       50 |      50 |    87.5 | 17                \n----------|---------|----------|---------|---------|-------------------\nTest Suites: 1 passed, 1 total\nTests:       2 passed, 2 total\nSnapshots:   0 total\nTime:        11.683s\n
Run Code Online (Sandbox Code Playgroud)\n\n

源代码:https://github.com/mrdulin/react-apollo-graphql-starter-kit/tree/master/stackoverflow/61408137

\n

  • 有什么办法可以让我用现有的代码来完成这项工作吗?或者我必须在每个测试用例上“mockReturnValue”?就像我想为正常情况有一个通用的模块结构......而对于边缘情况我想要一些“方法”来返回不同的值...... (2认同)