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

时间:2019-08-01 09:25:47

标签: reactjs firebase unit-testing jestjs react-testing-library

我想测试点击时调用firebase.auth().sendPasswordResetEmail()的组件,所以我想测试firebase是否被称为onClick,但不确定如何实现-我不想在api中调用api测试。

我希望获得有关模拟/拦截Firebase调用的一般指导。

我正在将React与Jest和React测试库一起使用。

这是有问题的组件

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)

这是我目前尝试模拟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)
})

但是我得到了错误:

  

预期模拟函数被调用了一次,但被调用了零次。

有人知道我在做什么错吗?

很多thaks

1 个答案:

答案 0 :(得分:0)

如果您使用的是create-react-app,则可以尝试在“ src”文件夹中添加“ 模拟”文件夹,然后在“ 内部添加“ firebase.js” >模仿”文件夹

在“ firebase.js”中:

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

export { mockFirebase as default };

“ fakeResponse”是您的预期响应。

然后在您的test.js中删除它们:

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

查看Jest官方网站以获取更多信息:https://jestjs.io/docs/en/manual-mocks