【问题标题】:React - Testing external function in a functional componentReact - 在功能组件中测试外部功能
【发布时间】:2019-08-06 22:23:40
【问题描述】:

我有一个使用反应钩子的功能组件。我有一个更新该组件状态的函数 (evaluateFunction)。

这个更新状态函数调用一个外部函数来检索数据,如下所示:

import { calculatePerformanceTime } from "../../helpers/calculate-performance-time";

const getChallenge = challengeNumber =>
    calculatePerformanceTime(
        require(`../../../challenges/${challengeNumber}.js`)[
            `dcpChallenge${challengeNumber}`
        ],
        challengeNumber
    );

export const TestComponent = _ => {
    const [inputs, setInputs] = useState({});
    const [result, setResult] = useState({});
    const evaluateFunction = value => setResult(getChallenge(value)(inputs));
    return (
        <div>
          <button onClick={() => evaluateFunction(1)} />
        </div>
    );
};

当我模拟单击以测试是否已调用 calculatePerformanceTime 时,它会抛出此错误:

TypeError: getChallenge(...) is not a function

我尝试导出 getChallenge,但没有成功。

如何测试单击按钮时是否调用了该函数?

这是我迄今为止一直在测试的:

import React from "react";
import Adapter from "enzyme-adapter-react-16";
import { configure, shallow } from "enzyme";
import { ChallengeSolution } from "./ChallengeSolution";
import { calculatePerformanceTime } from "../../helpers/calculate-performance-time";
configure({ adapter: new Adapter() });

const mockFunction = jest.fn();
const mockInputData = 1;

jest.mock(`!raw-loader!../../challenges/1.js`, () => "MOCK_RAW", {
    virtual: true
});

jest.mock(`!raw-loader!../../challenges/2.js`, () => "MOCK_RAW", {
    virtual: true
});

jest.mock("../../helpers/calculate-performance-time.js");

describe("ChallengeSolutionComponent", () => {
    let wrapper;
    const tabNumber = 2;
    beforeEach(() => {
        wrapper = shallow(<ChallengeSolution selectedTab={tabNumber} />);
    });

    describe("when component was mount", () => {
        it("should render form correctly", () => {
            const title = wrapper.find(".challenge-solution__title");
            const button = wrapper.find(".challenge-solution__button");
            button.simulate("click");
            expect(calculatePerformanceTime).toHaveBeenCalled();
            expect(title.text()).toEqual(`Daily Coding Solution #${tabNumber}`);
        });
    });
});

【问题讨论】:

  • 你能分享calculatePerformanceTime的代码和你的测试吗? (您的代码期望 getChallenge 返回一个 function 但我看不到足够的代码来判断是什么导致您的测试期间中断)
  • 我已经添加了我一直在做的测试。我认为这个问题是因为该组件是一个功能组件,并且由于getChallenge 在外面,它无法以某种方式到达它......如果你愿意,我可以分享calculatePerformanceTime(它很长)虽然getChallenge 是本身就是一个函数,所以calculatePerformanceTime的结果并不重要
  • 你根本不需要测试它。代码不正确。钩子只能在顶层运行。相反,您创建了一个稍后将调用该钩子的新函数。这不是受支持的行为。 reactjs.org/docs/hooks-overview.html#rules-of-hooks。 UPD:或者我可能会被你提到的钩子误导。这个calculatePerformanceTime 函数是钩子还是常规函数?
  • 不,calculatePerformanceTime 与钩子完全没有关系,只是一个返回某个值的函数。我确实在顶层使用了钩子,这个问题与模拟该特定功能有关。我需要将calculate-performance-time 作为全局模块导入才能正确模拟它:)

标签: javascript reactjs jestjs enzyme react-hooks


【解决方案1】:

这一行:

jest.mock("../../helpers/calculate-performance-time.js");

...将calculatePerformanceTime 设置为一个返回undefined 的空模拟函数。

由于getChallenge返回调用calculatePerformanceTime的结果,所以也返回undefined

那么,当这条线运行时:

const evaluateFunction = value => setResult(getChallenge(value)(inputs));

...它尝试将getChallenge(...) 的结果用作函数并使用inputs 调用它,但失败了,因为它试图将undefined 作为函数调用。


你需要模拟calculatePerformanceTime 来返回一个函数

import React from "react";
import Adapter from "enzyme-adapter-react-16";
import { configure, shallow } from "enzyme";
import { ChallengeSolution } from "./ChallengeSolution";
import * as calculatePerformanceTimeModule from "../../helpers/calculate-performance-time";  // import the module
configure({ adapter: new Adapter() });

const mockFunction = jest.fn();
const mockInputData = 1;

jest.mock(`!raw-loader!../../challenges/1.js`, () => "MOCK_RAW", {
  virtual: true
});

jest.mock(`!raw-loader!../../challenges/2.js`, () => "MOCK_RAW", {
  virtual: true
});

const spy = jest.spyOn(calculatePerformanceTimeModule, 'calculatePerformanceTime');
spy.mockReturnValue(() => { /* this returns a function...fill in the return value here */ });

describe("ChallengeSolutionComponent", () => {
  let wrapper;
  const tabNumber = 2;
  beforeEach(() => {
    wrapper = shallow(<ChallengeSolution selectedTab={tabNumber} />);
  });

  describe("when component was mount", () => {
    it("should render form correctly", () => {
      const title = wrapper.find(".challenge-solution__title");
      const button = wrapper.find(".challenge-solution__button");
      button.simulate("click");
      expect(spy).toHaveBeenCalled();  // Success!
      expect(title.text()).toEqual(`Daily Coding Solution #${tabNumber}`);
    });
  });
});

【讨论】:

    猜你喜欢
    • 2021-08-30
    • 2021-08-18
    • 2020-09-21
    • 2020-12-18
    • 2021-08-06
    • 1970-01-01
    • 2021-04-13
    • 2020-07-17
    • 2021-09-04
    相关资源
    最近更新 更多