首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么查询在单独的“in”测试块中失败

为什么查询在单独的“in”测试块中失败
EN

Stack Overflow用户
提问于 2022-11-16 13:50:32
回答 1查看 17关注 0票数 0

我有一个React组件。我用Jest作为跑步者编写测试,并编写测试库来编写测试。

注册组件代码(使用物化进行样式设计)是:

代码语言:javascript
运行
复制
import React, { useState } from "react";
import Card from "@material-ui/core/Card";
import CardActions from "@material-ui/core/CardActions";
import CardContent from "@material-ui/core/CardContent";
import Button from "@material-ui/core/Button";
import TextField from "@material-ui/core/TextField";
import Typography from "@material-ui/core/Typography";
import Icon from "@material-ui/core/Icon";
import { makeStyles } from "@material-ui/core/styles";
import { create } from "./api-user.js";
import Dialog from "@material-ui/core/Dialog";
import DialogActions from "@material-ui/core/DialogActions";
import DialogContent from "@material-ui/core/DialogContent";
import DialogContentText from "@material-ui/core/DialogContentText";
import DialogTitle from "@material-ui/core/DialogTitle";
import { Link } from "react-router-dom";

const useStyles = makeStyles((theme) => ({
  card: {
    maxWidth: 600,
    margin: "auto",
    textAlign: "center",
    marginTop: theme.spacing(5),
    paddingBottom: theme.spacing(2),
  },
  error: {
    verticalAlign: "middle",
  },
  title: {
    marginTop: theme.spacing(2),
    color: theme.palette.openTitle,
  },
  textField: {
    marginLeft: theme.spacing(1),
    marginRight: theme.spacing(1),
    width: 300,
  },
  submit: {
    margin: "auto",
    marginBottom: theme.spacing(2),
  },
}));

export default function Signup() {
  const classes = useStyles();
  const [values, setValues] = useState({
    name: "",
    password: "",
    email: "",
    open: false,
    error: "",
  });

  const handleChange = (name) => (event) => {
    setValues({ ...values, [name]: event.target.value });
  };

  const clickSubmit = () => {
    const user = {
      name: values.name || undefined,
      email: values.email || undefined,
      password: values.password || undefined,
    };
    create(user).then((data) => {
      if (data.error) {
        setValues({ ...values, error: data.error });
      } else {
        setValues({ ...values, error: "", open: true });
      }
    });
  };
  return (
    <div>
      <Card className={classes.card}>
        <CardContent>
          <Typography variant="h6" className={classes.title}>
            Sign Up
          </Typography>
          <TextField
            role="name"
            id="name"
            label="Name"
            className={classes.textField}
            value={values.name}
            onChange={handleChange("name")}
            margin="normal"
          />
          <br />
          <TextField
            role="email"
            id="email"
            type="email"
            label="Email"
            className={classes.textField}
            value={values.email}
            onChange={handleChange("email")}
            margin="normal"
          />
          <br />
          <TextField
            role="password"
            id="password"
            type="password"
            label="Password"
            className={classes.textField}
            value={values.password}
            onChange={handleChange("password")}
            margin="normal"
          />
          <br />{" "}
          {values.error && (
            <Typography component="p" color="error">
              <Icon color="error" className={classes.error}>
                error
              </Icon>
              {values.error}
            </Typography>
          )}
        </CardContent>
        <CardActions>
          <Button
            color="primary"
            variant="contained"
            onClick={clickSubmit}
            className={classes.submit}
          >
            Submit
          </Button>
        </CardActions>
      </Card>
      <Dialog open={values.open} disableBackdropClick={true}>
        <DialogTitle>New Account</DialogTitle>
        <DialogContent>
          <DialogContentText>
            New account successfully created.
          </DialogContentText>
        </DialogContent>
        <DialogActions>
          <Link to="/signin">
            <Button color="primary" autoFocus="autoFocus" variant="contained">
              Sign In
            </Button>
          </Link>
        </DialogActions>
      </Dialog>
    </div>
  );
}

我正在尝试呈现组件,然后验证表单是否有NameEmailPassword输入。测试文件如下所示:

代码语言:javascript
运行
复制
import React from "react";
import { screen, render, cleanup, fireEvent } from "@testing-library/react";
import SignUp from "./Signup";

describe("App component", () => {
  beforeAll(() => {
    render(<SignUp />);
  });
  it("should have the input field for name", () => {
    const nameInput = screen.getByLabelText("Name");
    expect(nameInput).toBeInTheDocument();
  });
  it("should have the input field for email", () => {
    const emailInput = screen.getByLabelText("Email");
    expect(emailInput).toBeInTheDocument();
  });
  it("should have the input field for password", () => {
    const passwordInput = screen.getByLabelText("Password");
    expect(passwordInput).toBeInTheDocument();
  });
  afterAll(cleanup);
});

问题:无论我测试输入的顺序如何,第一个用例/测试总是通过的。.getByLabelText查询能够找到第一个it块的组件,并在下一个it块中失败。

运行上述文件测试的消息是:

代码语言:javascript
运行
复制
 FAIL  client/user/SignUp.test.js
  App component
    ✓ should have the input field for name (13 ms)
    ✕ should have the input field for email (3 ms)
    ✕ should have the input field for password (1 ms)

  ● App component › should have the input field for email

    TestingLibraryElementError: Unable to find a label with the text of: Email

    Ignored nodes: comments, script, style
    <body />

      12 |   });
      13 |   it("should have the input field for email", () => {
    > 14 |     const emailInput = screen.getByLabelText("Email");
         |                               ^
      15 |     expect(emailInput).toBeInTheDocument();
      16 |   });
      17 |   it("should have the input field for password", () => {

      at Object.getElementError (node_modules/@testing-library/dom/dist/config.js:40:19)
      at getAllByLabelText (node_modules/@testing-library/dom/dist/queries/label-text.js:116:38)
      at node_modules/@testing-library/dom/dist/query-helpers.js:62:17
      at node_modules/@testing-library/dom/dist/query-helpers.js:111:19
      at Object.getByLabelText (client/user/SignUp.test.js:14:31)

  ● App component › should have the input field for password

当我把命令转到:

代码语言:javascript
运行
复制
 it("should have the input field for email", () => {
    const emailInput = screen.getByLabelText("Email");
    expect(emailInput).toBeInTheDocument();
  });
  it("should have the input field for name", () => {
    const nameInput = screen.getByLabelText("Name");
    expect(nameInput).toBeInTheDocument();
  });
  it("should have the input field for password", () => {
    const passwordInput = screen.getByLabelText("Password");
    expect(passwordInput).toBeInTheDocument();
  });

消息更改为:

代码语言:javascript
运行
复制
FAIL  client/user/SignUp.test.js
  App component
    ✓ should have the input field for email (19 ms)
    ✕ should have the input field for name (8 ms)
    ✕ should have the input field for password (6 ms)

  ● App component › should have the input field for name

    TestingLibraryElementError: Unable to find a label with the text of: Name

    Ignored nodes: comments, script, style
    <body />

      13 |   });
      14 |   it("should have the input field for name", () => {
    > 15 |     const nameInput = screen.getByLabelText("Name");
         |                              ^
      16 |     expect(nameInput).toBeInTheDocument();
      17 |   });
      18 |   it("should have the input field for password", () => {

      at Object.getElementError (node_modules/@testing-library/dom/dist/config.js:40:19)
      at getAllByLabelText (node_modules/@testing-library/dom/dist/queries/label-text.js:116:38)
      at node_modules/@testing-library/dom/dist/query-helpers.js:62:17
      at node_modules/@testing-library/dom/dist/query-helpers.js:111:19
      at Object.getByLabelText (client/user/SignUp.test.js:15:30)

  ● App component › should have the input field for password

    TestingLibraryElementError: Unable to find a label with the text of: Password

    Ignored nodes: comments, script, style
    <body />

      17 |   });
      18 |   it("should have the input field for password", () => {
    > 19 |     const passwordInput = screen.getByLabelText("Password");
         |                                  ^
      20 |     expect(passwordInput).toBeInTheDocument();
      21 |   });
      22 |   afterAll(cleanup);

      at Object.getElementError (node_modules/@testing-library/dom/dist/config.js:40:19)
      at getAllByLabelText (node_modules/@testing-library/dom/dist/queries/label-text.js:116:38)
      at node_modules/@testing-library/dom/dist/query-helpers.js:62:17
      at node_modules/@testing-library/dom/dist/query-helpers.js:111:19
      at Object.getByLabelText (client/user/SignUp.test.js:19:34) 

正如您现在所看到的,对email的查询相对于其他2(nameemail)有效。

更有趣的是,当我在一个it块中使用所有3个查询时,所有测试都通过了:

代码语言:javascript
运行
复制
it("should have the input field for name", () => {
    const nameInput = screen.getByLabelText("Name");
    expect(nameInput).toBeInTheDocument();
    const emailInput = screen.getByLabelText("Email");
    expect(emailInput).toBeInTheDocument();
    const passwordInput = screen.getByLabelText("Password");
    expect(passwordInput).toBeInTheDocument();
  }); 

它验证了所有3个查询,您可以通过将参数更改为查询来测试它(SodeSandBox:https://codesandbox.io/s/react-testing-library-material-ui-select-forked-5rixw3?file=/src/App.test.js:254-891),如果您将它更改为像const emailInput = screen.getByLabelText("Email-failing");一样,它将失败。

有人能告诉我,为什么测试库在同一个块中工作,而不是在单独的块中工作?我如何测试三个输入?我还尝试过不同的查询方法,例如角色属性的.getByRole,它的行为方式是相同的,即在单个块中工作,而第2和第3块/测试失败。

EN

Stack Overflow用户

回答已采纳

发布于 2022-11-16 13:54:30

在进行所有测试之前,您将呈现组件。相反,您应该在每个测试中呈现组件。不要在beforeAll块中使用呈现,在每个' it‘块中使用它。

代码语言:javascript
运行
复制
import React from "react";
import { screen, render, cleanup, fireEvent } from "@testing- 
library/react";
import SignUp from "./Signup";

describe("App component", () => {
  it("should have the input field for name", () => {
    render(<SignUp />);
    const nameInput = screen.getByLabelText("Name");
    expect(nameInput).toBeInTheDocument();
  });
  it("should have the input field for email", () => {
    render(<SignUp />);
    const emailInput = screen.getByLabelText("Email");
    expect(emailInput).toBeInTheDocument();
  });
  it("should have the input field for password", () => {
    render(<SignUp />);
    const passwordInput = screen.getByLabelText("Password");
    expect(passwordInput).toBeInTheDocument();
  });
  afterAll(cleanup);
});
票数 0
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74461629

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档