为 React App 开玩笑模拟 Firebase auth signInWithPopUp
Mocking Firebase auth signInWithPopUp with jest for React App
我在测试我的 React 应用程序登录方法时遇到了一些问题。当我在测试中单击登录按钮时,我试图模拟 firebase auth 的 signInWithPopup 方法。
我的登录处理程序在 App.js
import * as firebase from 'firebase/app';
import 'firebase/auth';
import firebaseSetup from './firebaseSetup'
const firebaseApp = firebaseSetup.firebaseApp
const firebaseAppAuth = firebaseSetup.firebaseAppAuth
const providers = firebaseSetup.providers
handleGoogleLogin = () => {
firebaseAppAuth.signInWithPopup(providers.googleProvider)
.then(function(result) {
this.setState({
token: result.credential.accessToken,
signedInUser: result.user
})
}).catch(function(error) {
let errorCode = error.code
let errorMessage = error.message
let errorEmail = error.email
let errorCredential = error.credential
})
}
我的mockFirebase.js
import * as firebase from 'firebase/app'
import firebaseConfig from './firebaseConfig';
import 'firebase/auth'
import App from './App'
import firebaseSetup from './firebaseSetup'
const mockFirebase = jest.fn( (functionName) => {
console.log('mockFirebase', typeof functionName.providerId)
switch(functionName.providerId) {
case 'google.com': {
console.log('google case')
return 'result of signInWithPopup'
}
default: {
throw new Error(`Unhandled firebase request: ${url}`)
}
}
})
beforeAll(() => {
jest.spyOn(firebaseSetup.firebaseAppAuth, 'signInWithPopup')
})
beforeEach(() => {
firebaseSetup.firebaseAppAuth.signInWithPopup.mockImplementation(mockFirebase)
})
export default mockFirebase
我的App.test.js
it('Firebase auth triggered when login clicked', async () => {
render(<App/>)
const result = fireEvent.click(screen.getByText(/Sign in with Google/i))
expect(mockFirebase).toBeCalled()
expect(result).toEqual(
'result of signInWithPopup'
)
})
我的测试失败并出现以下错误:
未捕获 [TypeError: firebaseAppAuth.signInWithPopup(...).then 不是函数]
如果我删除 .then 块,测试将在 expect(result).toEqual('result of signInWithPopup') 上失败并出现错误:
预期:“signInWithPopup 的结果”
收到:真实
我不确定为什么 .then 块会导致错误,或者为什么当测试单击登录按钮时我无法在我的结果常量中的 mockFirebase 函数中获得匹配开关案例的 return 结果.
iotype 的建议加上将我的测试结构更改为以下内容解决了这个问题。
it('Firebase auth triggerd when login clicked', async () => {
fireEvent.click(screen.getByText(/Sign in with Google/i))
await waitForElementToBeRemoved(() => screen.getByText(/Sign In With Google/i))
expect(screen.getByText(/Welcome to Writual/i)).toBeInTheDocument()
})
})
我想问题是 signInWithPopup
是一个提供 then
方法的 Promise。因此模拟必须 return 具有相同签名的 Promise。
我在测试我的 React 应用程序登录方法时遇到了一些问题。当我在测试中单击登录按钮时,我试图模拟 firebase auth 的 signInWithPopup 方法。
我的登录处理程序在 App.js
import * as firebase from 'firebase/app';
import 'firebase/auth';
import firebaseSetup from './firebaseSetup'
const firebaseApp = firebaseSetup.firebaseApp
const firebaseAppAuth = firebaseSetup.firebaseAppAuth
const providers = firebaseSetup.providers
handleGoogleLogin = () => {
firebaseAppAuth.signInWithPopup(providers.googleProvider)
.then(function(result) {
this.setState({
token: result.credential.accessToken,
signedInUser: result.user
})
}).catch(function(error) {
let errorCode = error.code
let errorMessage = error.message
let errorEmail = error.email
let errorCredential = error.credential
})
}
我的mockFirebase.js
import * as firebase from 'firebase/app'
import firebaseConfig from './firebaseConfig';
import 'firebase/auth'
import App from './App'
import firebaseSetup from './firebaseSetup'
const mockFirebase = jest.fn( (functionName) => {
console.log('mockFirebase', typeof functionName.providerId)
switch(functionName.providerId) {
case 'google.com': {
console.log('google case')
return 'result of signInWithPopup'
}
default: {
throw new Error(`Unhandled firebase request: ${url}`)
}
}
})
beforeAll(() => {
jest.spyOn(firebaseSetup.firebaseAppAuth, 'signInWithPopup')
})
beforeEach(() => {
firebaseSetup.firebaseAppAuth.signInWithPopup.mockImplementation(mockFirebase)
})
export default mockFirebase
我的App.test.js
it('Firebase auth triggered when login clicked', async () => {
render(<App/>)
const result = fireEvent.click(screen.getByText(/Sign in with Google/i))
expect(mockFirebase).toBeCalled()
expect(result).toEqual(
'result of signInWithPopup'
)
})
我的测试失败并出现以下错误: 未捕获 [TypeError: firebaseAppAuth.signInWithPopup(...).then 不是函数]
如果我删除 .then 块,测试将在 expect(result).toEqual('result of signInWithPopup') 上失败并出现错误:
预期:“signInWithPopup 的结果” 收到:真实
我不确定为什么 .then 块会导致错误,或者为什么当测试单击登录按钮时我无法在我的结果常量中的 mockFirebase 函数中获得匹配开关案例的 return 结果.
iotype 的建议加上将我的测试结构更改为以下内容解决了这个问题。
it('Firebase auth triggerd when login clicked', async () => {
fireEvent.click(screen.getByText(/Sign in with Google/i))
await waitForElementToBeRemoved(() => screen.getByText(/Sign In With Google/i))
expect(screen.getByText(/Welcome to Writual/i)).toBeInTheDocument()
})
})
我想问题是 signInWithPopup
是一个提供 then
方法的 Promise。因此模拟必须 return 具有相同签名的 Promise。