簡體   English   中英

使用 react-testing-library 和 jest 測試是否調用了 prop 函數

[英]Testing if a prop function was called using react-testing-library and jest

我正在嘗試編寫一個簡單的測試來驗證當用戶與幾個按鈕交互時是否調用了一個道具。 這是我的測試:

  it('submits the name on save', async () => {
    const name = 'Some name'
    const updatedName = 'New name'

    const onSubmit = jest.fn()

    render(
      <EditableName name={name} onSubmit={onSubmit} />
    )

    act(() => {
      fireEvent.click(getByText('Edit'))
      fireEvent.change(getByRole('input'), { target: { value: updatedName } })
      fireEvent.click(getByText('Save'))
    })

    expect(onSubmit).toBeCalledTimes(1)
  })

結果:

 ● EditableName › submits the name on save

    expect(jest.fn()).toBeCalledTimes(expected)

    Expected number of calls: 1
    Received number of calls: 0

當我在console.log中查看是否正在到達調用onSubmit的行時,我可以看到它是。

我懷疑問題在於,當我斷言.toBeCalledTimes()時,我期望的onSubmit函數是該函數的不同實例。 由於我觸發的三個事件導致組件重新渲染。

如何確保我在測試中作為道具傳遞的函數與被調用的函數相同? 我需要使用spyOn嗎? 如果是這樣,如何?

提前致謝!

編輯:這是組件的最小代碼示例:

import React, { useState } from "react";
import { Box, Button, TextField, Typography } from "@material-ui/core";

const EditableName = ({ name, onSubmit }) => {
  const [editing, setEditing] = useState(false);
  const [value, setValue] = useState(name);

  const handleSubmit = () => {
    onSubmit({ name: value });
  };

  const handleToggleEditMode = () => {
    if (editing) {
      setEditing(false);
      setValue(name);
    } else {
      setEditing(true);
    }
  };

  if (!editing) {
    return (
      <>
        <Typography display="inline" variant="h5" component="h1">
          {name}
        </Typography>
        <Button onClick={handleToggleEditMode}>
          Edit
        </Button>
      </>
    );
  }

  return (
    <>
      <TextField
        name="name"
        variant="outlined"
        fullWidth
        size="small"
        label="Subsidy name"
        value={value}
        onChange={(e) => setValue(e.target.value)}
        inputProps={{ role: "input" }}
      />
      <Button onClick={handleSubmit}>Save</Button>
    </>
  );
};

export default EditableName;

我認為您需要將事件分開,並且act內置於 RTL 中,因此您需要使用await waitFor代替:

    await waitFor(() => {
      fireEvent.click(getByText('Edit'))
    });
//should probably assert changes here
    await waitFor(() => {
      fireEvent.change(getByRole('input'), { target: { value: updatedName } })
    });
//should probably assert changes here
    await waitFor(() => {
      fireEvent.click(getByText('Save'))
    })
    expect(onSubmit).toBeCalledTimes(1)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM