如何模拟Reaction测试中的状态和数据的值 [英] How can mock the value of a state and data in my react test

查看:11
本文介绍了如何模拟Reaction测试中的状态和数据的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为我的Reaction页面编写测试,但我的页面在其状态下使用isLoding,当加载页面时呈现"正在加载",当加载但没有数据(来自FETCH请求)时呈现"找不到数据",而当加载数据(来自FETCH请求)时加载欢迎页面。

我想编写一个测试,用于检查在下列情况下是否显示预期文本:

  • 页面已加载,但未找到数据
  • 页面已加载并包含数据
我认为我已经控制了没有数据测试可以正常工作,但是当我试图模拟它返回的数据时,我收到了错误消息。错误消息为

TypeError: Cannot read property 'map' of undefined

但我不确定为什么我的模拟数据是Data:Orders>;,其中包含数据,因此不应该是未定义的。

有人能告诉我如何改正测试吗?

WelcomePage.js

import React from "react";
import { Link } from "react-router-dom";

class WelcomePage extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      data: [],
      isLoading: false,
    };
  }

  componentDidMount() {
    this.setState({ isLoading: true });
    const proxyurl = "https://cors-anywhere.herokuapp.com/";
    const url =
      "mu url"
    fetch(proxyurl + url)
      .then((res) => res.json())
      .then((data) => this.setState({ data: data, isLoading: false }));
  }

  render() {
    const { data, isLoading } = this.state;
    if (isLoading) {
      return (
        <div className="pageLoading">
        <p>Loading...</p>
        </div>
      );
    }
    if (data.length === 0) {
      return <p> no data found</p>;
    }
    return (
      <div className="Welcome">
        <div className="Details">
          <p className="userID">
            <strong>
              Welcome {data.userForename} {data.userSurname}
            </strong>
          </p>
          <button className="SignOut">
            <Link to={{ pathname: "/LogIn" }}>Sign Out</Link>
          </button>
        </div>
        <div className="InfoBox">
          <p>
            <strong>Orders</strong>{" "}
          </p>
        </div>
        <div className="orderss">
          {data.orders.map((order, index) => (
          <ul className="orderBox" key={order.toString()+index}>
            <li className="orderLink">
              <Link
                to={{
                  pathname: "/OrderDetails",
                  state: {
                    orderNumber: order.rollNumber,
                    userID: this.state.userID,
                  },
                }}
                >
                Order number: {order.rollNumber}
              </Link>
            </li>
            <li> Customer name: {order.customerFullName}</li>
          </ul>
          ))}
        </div>
      </div>
    );
  }
}

export default WelcomePage;

欢迎.页面.测试.js

import React, { useState } from 'react';
import renderer from 'react-test-renderer';
import {render, unmountComponentAtNode } from 'react-dom';
import WelcomePage from './WelcomePage';

let container = null;

beforeEach(() => {
  container = document.createElement('div');
  document.body.appendChild(container);
})

afterEach(() => {
  unmountComponentAtNode(container);
  container.remove();
  container = null;
})

test("test page renders as epxected when loading", () => {
  const userId= "123456";
  render(<WelcomePage location={userId}></UserWelcome>, container);
  expect(container.innerHTML).toContain("Loading...");
});

test("mock fetch call, empty responce from db should return no data", 
  async () => {
    const fakeResponse = [];
    const userId = "1234567";

    jest.spyOn(window, "fetch").mockImplementation(() => {
      const fetchResponse = {
        json: () => Promise.resolve(fakeResponse),
      };
      return Promise.resolve(fetchResponse);
    });

    await act(async () => {
      render(<WelcomePage location={userId} />, container);
    });

    expect(container.innerHTML).toContain("no data");

    window.fetch.mockRestore();
  }
);

test("mock fetch call, valid responce from db should return applications", async () => {
  //{ rates: { CAD: 1.42 } }
  const fakeResponse = [
    {
      data: {
        userId: 1234567,
        userForename: "Joe",
        userSurname: "Bloggs",
        orders: [
          {
            orderNumber: 10000000001,
            customerFullName: "Mrs Joes Bloggs",
            userId: 1234567
          },
        ]
      }
    }
  ];
  const userId = "1234567";

  jest.spyOn(window, "fetch").mockImplementation(() => {
    const fetchResponse = {
      json: () => Promise.resolve(fakeResponse)
    };
    return Promise.resolve(fetchResponse);
  });

  await act(async () => {
    render(<WelcomePage location={userId} />, container);
  });

  expect(container.textContent).toContain("Order number: 10000000001");

  window.fetch.mockRestore();
});

编辑-添加Package.json

{
  "name": "sm-app",
  "version": "0.1.0",
  "private": false,
  "dependencies": {
    "@testing-library/jest-dom": "^4.2.4",
    "@testing-library/react": "^9.5.0",
    "@testing-library/user-event": "^7.2.1",
    "bootstrap": "^4.5.3",
    "moment": "^2.29.1",
    "prop-types": "^15.7.2",
    "react": "^17.0.1",
    "react-app-polyfill": "^2.0.0",
    "react-bootstrap": "^1.4.0",
    "react-dom": "^17.0.1",
    "react-router-dom": "^5.2.0",
    "react-scripts": "3.4.4",
    "react-spinners": "^0.9.0",
    "reactstrap": "^8.6.0"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all",
      "ie >= 9"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version",
      "ie 11"
    ]
  },
  "devDependencies": {
    "prettier": "2.1.2",
    "react-test-renderer": "^17.0.1"
  }
}

推荐答案

测试用例

如您所见,您传递了不包含订单的空数组

test("mock fetch call, empty responce from db should return no data", 
  async () => {
    const fakeResponse = []; <-- empty array which does not contain orders
    const userId = "1234567";

    jest.spyOn(window, "fetch").mockImplementation(() => {
      const fetchResponse = {
        json: () => Promise.resolve(fakeResponse),
      };
      return Promise.resolve(fetchResponse);
    });

    await act(async () => {
      render(<WelcomePage location={userId} />, container);
    });

    expect(container.innerHTML).toContain("no data");

    window.fetch.mockRestore();
  }
);

因为它试图访问undefinedundefined没有map功能的订单时数据为空

{data.orders.map((order, index) => ( <-- problems here
    <ul className="orderBox" key={order.toString()+index}>
        <li className="orderLink">
            <Link
                to={{
                    pathname: "/OrderDetails",
                    state: {
                        orderNumber: order.rollNumber,
                        userID: this.state.userID,
                    },
                }}
            >
                Order number: {order.rollNumber}
            </Link>
        </li>
        <li> Customer name: {order.customerFullName}</li>
    </ul>
))}

您可以这样更改它:

{data && data.orders && data.orders.map((order, index) => ( <-- changes
    <ul className="orderBox" key={order.toString()+index}>
        <li className="orderLink">
            <Link
                to={{
                    pathname: "/OrderDetails",
                    state: {
                        orderNumber: order.rollNumber,
                        userID: this.state.userID,
                    },
                }}
            >
                Order number: {order.rollNumber}
            </Link>
        </li>
        <li> Customer name: {order.customerFullName}</li>
    </ul>
))}

注意:


  • fakeResponse作为数组传递时,需要将WelcomePage.js中的FETCH内setState更新为
if (data && data[0] && data[0]['data']) {
    this.setState({
        data: data[0]['data'], <-- changes
        isLoading: false,
    });
}

  • 或将fakeResponse更改为:
const fakeResponse = {
  data: {
    userId: 1234567,
    userForename: "Joe",
    userSurname: "Bloggs",
    orders: [
      {
        orderNumber: 10000000001,
        customerFullName: "Mrs Joes Bloggs",
        userId: 1234567
      },
    ]
  }
};

将状态设置为:

if (data && data['data']) {
    this.setState({
        data: data['data'], <-- changes
        isLoading: false,
    });
}

检查数据是否为空的AND条件:

if (Object.keys(data).length === 0) {
    return <p> no data found</p>;
}

这篇关于如何模拟Reaction测试中的状态和数据的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆