如何使用 Sinon 和 ReactJS 模拟模块导入
How to mock a module import with Sinon and 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);
});
});
我正在尝试为我用 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);
});
});