React - 在功能组件中测试外部功能
Posted
技术标签:
【中文标题】React - 在功能组件中测试外部功能【英文标题】:React - Testing external function in a functional component 【发布时间】: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
作为全局模块导入才能正确模拟它:)
【参考方案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`);
);
);
);
【讨论】:
以上是关于React - 在功能组件中测试外部功能的主要内容,如果未能解决你的问题,请参考以下文章
React Native - 在功能组件中创建方法并在组件外部调用此方法,可能吗?
使用 Jest/Enzyme 在 React 功能组件中测试封闭组件
在 React 功能组件中使用 ref 添加测试鼠标事件监听器