reactjs - 如何使用 Sinon 和 ReactJS 模拟模块导入
问题描述
我正在尝试为我用 TS 编写的 React 组件之一编写单元测试:
import React, { useContext } from 'react';
import Lottie from 'lottie-react-web';
import { ConfigContext } from '../ConfigProvider';
import type { UIKitFC } from '../../types/react-extensions';
// interfaces
export interface LoadingOverlayProps {
size: 'large' | 'medium' | 'small';
testId?: string;
}
interface LoaderProps {
size: 'large' | 'medium' | 'small';
}
const G3Loader: React.FC<LoaderProps> = ({ size }) => {
const options = { animationData };
const pxSize =
size === 'small' ? '100px' : size === 'medium' ? '200px' : '300px';
const height = pxSize,
width = pxSize;
return (
<div className="loader-container">
<Lottie options={options} height={height} width={width} />
<div className="loader__loading-txt">
<div>
<h4>Loading...</h4>
</div>
</div>
</div>
);
};
/**
* Description of Loading Overlay component
*/
export const LoadingOverlay: UIKitFC<LoadingOverlayProps> = (props) => {
const { testId } = props;
const { namespace } = useContext(ConfigContext);
const { baseClassName } = LoadingOverlay.constants;
const componentClassName = `${namespace}-${baseClassName}`;
const componentTestId = testId || `${namespace}-${baseClassName}`;
return (
<div id={componentTestId} className={componentClassName}>
<G3Loader size={props.size} />
</div>
);
};
LoadingOverlay.constants = {
baseClassName: 'loadingOverlay',
};
LoadingOverlay.defaultProps = {
testId: 'loadingOverlay',
};
export default LoadingOverlay;
该组件使用导入的模块“Lottie”进行一些动画,但我对测试它不感兴趣,我只想测试我的组件及其道具。
问题是,当我运行单元测试时,出现错误: 错误:未实现:HTMLCanvasElement.prototype.getContext(未安装 canvas npm 包)
经过一些研究,我得出的结论是错误是由Lottie导入引起的,所以我想模拟它以进行测试。我正在使用 Mocha 和 Sinon 的存根功能来尝试模拟库导入,但同样的错误仍然存在,让我觉得我没有正确地存根模块。这是我在单元测试中的最新尝试:
import React from 'react';
import * as Lottie from 'lottie-react-web';
import { render } from '@testing-library/react';
import { expect } from 'chai';
import * as sinon from 'sinon';
import LoadingOverlay from '../src/components/LoadingOverlay';
const TEST_ID = 'the-test-id';
const FakeLottie: React.FC = (props) => {
return <div>{props}</div>;
};
describe('Loading Overlay', () => {
// beforeEach(function () {
// sinon.stub(Lottie, 'default').callsFake((props) => FakeLottie(props));
// });
console.log('11111');
it('should have a test ID', () => {
sinon.stub(Lottie, 'default').callsFake((props) => FakeLottie(props));
console.log(Lottie);
const { getByTestId, debug } = render(
<LoadingOverlay testId={TEST_ID} size="small" />
);
debug();
expect(getByTestId(TEST_ID)).to.not.equal(null);
});
});
我不太确定还能尝试什么,单元测试不是我的强项……如果有人可以提供帮助,那就太好了。
解决方案
我回答了我自己的问题......发帖以防其他人遇到同样的问题。
该错误抱怨HTMLCanvasElement。事实证明,我试图存根的组件正在使用Canvas库本身,这在浏览器中运行时不需要,但由于我正在构建测试,我只是将Canvas库添加到我的包中,问题就解决了. 完整代码如下:
import React from 'react';
import { render, cleanup } from '@testing-library/react';
import { expect, assert } from 'chai';
import * as lottie from 'lottie-react-web';
import { createSandbox } from 'sinon';
import LoadingOverlay from '../src/components/LoadingOverlay';
// test ID
const TEST_ID = 'the-test-id';
// mocks
const sandbox = createSandbox();
const MockLottie = () => 'Mock Lottie';
describe('Loading Overlay', () => {
beforeEach(() => {
sandbox.stub(lottie, 'default').callsFake(MockLottie);
});
afterEach(() => {
sandbox.restore();
cleanup();
});
it('should have test ID', () => {
const { getByTestId } = render(
<LoadingOverlay testId={TEST_ID} size="medium" />
);
expect(getByTestId(TEST_ID)).to.not.equal(null);
});
});
推荐阅读
- jasper-reports - 如何在文本字段中强制中断长文本
- python - 使用 easydict 重写此代码。argparse 无法正常工作
- php - 递归查询以获取用户列表
- python - 如何在 Linux VM 中从 Windows 构建 linux 容器?
- mongodb - MongoDB 聚合管道 $facet 不使用索引
- amazon-web-services - AWS DynamoDB 如何计算 Query 的读取单位?
- flutter - Provider Widget 的放置位置——Flutter Provider Package
- android - 找不到“libconscrypt_jni.so”
- c# - 如何取消 UWP XAML NavigationView 控件中的验证导航
- r - 如何处理函数中参数周围的引号?