简体   繁体   English

使用Jest和React Testing库在React应用程序中模拟Firebase时发生错误

[英]Errors when mocking firebase within a React app using Jest and React Testing Library

I want to test a component which calls firebase.auth().sendPasswordResetEmail() on click, so I want to test that firebase is being called onClick, but am not sure how to implement - I don't want to call the api in a test. 我想测试点击时调用firebase.auth().sendPasswordResetEmail()的组件,所以我想测试firebase是否被称为onClick,但不确定如何实现-我不想在其中调用api一个测试。

I would love some guidance on mocking/intercepting firebase calls in general. 通常,我希望获得有关模拟/拦截Firebase调用的一些指导。

I am using React with Jest and React Testing Library. 我正在使用带有Jest和React测试库的React。

This is the component in question: 这是有问题的组件:

import React from 'react'
import { withFirebase } from '../Firebase'

interface PFProps {
  firebase: firebase.app.App
}

interface S {
  email: string
}

interface Error {
  message?: string
}

const PasswordForget = ({ firebase }: PFProps) => {
  const initialState = { email: '' }
  const stateReducer = (state: S, update: { [x: string]: string }) => ({
    ...state,
    ...update,
  })
  const [state, dispatch] = React.useReducer(stateReducer, initialState)
  const [error, setError] = React.useState<Error>()

  const isValid = () => validator.isEmail(state.email)

  const handleSubmit = (event: React.FormEvent) => {
    event.preventDefault()

    if (!isValid()) {
      return setError({ message: messages.emailIsInvalid })
    }

    firebase
      .auth()
      .sendPasswordResetEmail(state.email)
      .then(success => console.log(success))
      .catch(error => setError(error))
    dispatch(initialState)
  }

  const handleChange = ({
    currentTarget: { name, value },
  }: React.ChangeEvent<HTMLInputElement>) => {
    setError(undefined)
    dispatch({ [name]: value })
  }

  return (
    <>
      <form onSubmit={handleSubmit} data-testid="form" noValidate>
        {error && error.message && <FormErrorPanel message={error.message} />}
        <Input
          type="email"
          name="email"
          data-testid="pwf-email"
          value={state.email}
          onChange={handleChange}
          placeholder="Enter your email address"
        />
        <Button>Reset password</Button>
      </form>
    </>
  )
}

const PasswordForgetLink = () => (
  <p>
    <Link to={ROUTES.PASSWORD_FORGET}>Forgotten password</Link>
  </p>
)

export { PasswordForgetLink }
export default withFirebase(PasswordForget)

This is how I am currently trying to mock firebase: 这是我目前尝试模拟Firebase的方式:

import React from 'react'
import '@testing-library/jest-dom/extend-expect'
import { render, cleanup, fireEvent } from '@testing-library/react'
import { FirebaseContext } from '../../Firebase'
import firebase from '../../Firebase'

import PasswordForget from '../index'

jest.mock('../../Firebase/firebase', () => {
  return {
    auth: jest.fn(() => ({
      sendPasswordResetEmail: jest.fn(() => Promise.resolve()),
    })),
  }
})

afterEach(cleanup)

const setup = () => {
  const utils = render(
    <FirebaseContext.Provider value={firebase}>
      <PasswordForget />
    </FirebaseContext.Provider>,
  )
  const form = utils.getByTestId('form')
  const emailInput = utils.getByTestId('pwf-email') as HTMLInputElement
  const h1 = utils.getByText(/Forgotten Password/i)
  return {
    h1,
    form,
    emailInput,
    ...utils,
  }
}

test('should call sendPasswordResetEmail method when the form is submitted with a valid email', () => {
  const { form, emailInput } = setup()
  const email = 'peterparker@foo.com'
  fireEvent.change(emailInput, { target: { value: email } })
  expect(emailInput.value).not.toBeNull()
  fireEvent.submit(form)
  expect(firebase.auth().sendPasswordResetEmail).toHaveBeenCalledTimes(1)
})

But I am getting the error: 但是我得到了错误:

Expected mock function to have been called one time, but it was called zero times. 预期模拟函数已被调用一次,但被调用了零次。

Does anyone know what I am doing wrong? 有人知道我在做什么错吗?

Many thaks 很多thak

If you're using create-react-app, you can try to add a " mocks " folder inside the "src" folder, then add a "firebase.js" inside " mocks " folder 如果您使用的是create-react-app,则可以尝试在“ src”文件夹中添加一个“ mocks ”文件夹,然后在“ mocks ”文件夹中添加一个“ firebase.js”

in "firebase.js": 在“ firebase.js”中:

const mockFirebase = {
  auth: jest.fn(() => mockFirebase ),
  sendPasswordResetEmail: jest.fn(() => Promise.resolve(fakeResponse))
};

export { mockFirebase as default };

"fakeResponse" is your expected response. “ fakeResponse”是您的预期响应。

then delete these in your test.js: 然后在test.js中删除它们:

jest.mock('../../Firebase/firebase', () => {
  return {
    auth: jest.fn(() => ({
      sendPasswordResetEmail: jest.fn(() => Promise.resolve()),
    })),
  }
})

check the Jest official site for more info: https://jestjs.io/docs/en/manual-mocks 请查看Jest官方网站以获取更多信息: https : //jestjs.io/docs/en/manual-mocks

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM