You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Sinon在ReactJS中Mock Lottie模块导入解决单元测试报错

问题原因

你原有代码的Stub不生效的核心原因是ES模块的导入提升:当你在测试文件顶部import LoadingOverlay from '../src/components/LoadingOverlay'时,组件内部已经完成了对真实lottie-react-web模块的导入和引用,后续你在测试用例中Stub的只是当前测试文件引入的Lottie对象,完全不会影响组件内部已经拿到的真实Lottie组件引用,所以canvas相关错误依然存在。

另外你代码还有两个潜在问题:

  • 自定义的FakeLottie直接返回<div>{props}</div>会报错,对象不能直接作为React子元素渲染
  • 组件使用了ConfigContext,测试时没有用Provider包裹传入值,会触发namespace未定义的错误

解决方案

推荐使用proxyquire做动态依赖替换,在加载组件前就替换掉lottie依赖:

步骤1:安装依赖

npm install proxyquire @types/proxyquire --save-dev

步骤2:修改测试代码

import React from 'react';
import { render } from '@testing-library/react';
import { expect } from 'chai';
import * as sinon from 'sinon';
import proxyquire from 'proxyquire';
import { ConfigContext } from '../src/ConfigProvider';

const TEST_ID = 'the-test-id';
// Mock Context值
const mockContextValue = { namespace: 'test' };
// 假Lottie组件
const FakeLottie = () => <div data-testid="fake-lottie"></div>;

// 动态加载LoadingOverlay,直接替换它的lottie-react-web依赖
const { default: LoadingOverlay } = proxyquire(
  '../src/components/LoadingOverlay',
  { 'lottie-react-web': { default: FakeLottie } }
);

describe('Loading Overlay', () => {
  it('should have a test ID', () => {
    const { getByTestId } = render(
      <ConfigContext.Provider value={mockContextValue}>
        <LoadingOverlay testId={TEST_ID} size="small" />
      </ConfigContext.Provider>
    );
    expect(getByTestId(TEST_ID)).to.exist;
  });

  // 还可以扩展测试验证size参数生效
  it('should pass correct size to Lottie', () => {
    const stubLottie = sinon.stub().returns(null);
    // 重新加载组件替换成带stub的Lottie
    const { default: SizeTestLoadingOverlay } = proxyquire(
      '../src/components/LoadingOverlay',
      { 'lottie-react-web': { default: stubLottie } }
    );
    render(
      <ConfigContext.Provider value={mockContextValue}>
        <SizeTestLoadingOverlay size="large" />
      </ConfigContext.Provider>
    );
    expect(stubLottie.firstCall.args[0].height).to.equal('300px');
  });
});

全局Mock方案(多测试文件复用)

如果多个测试文件都需要Mock lottie,可以用mock-require做全局替换:

  1. 安装依赖:npm install mock-require --save-dev
  2. 新建测试启动脚本test/setup.js:
const mock = require('mock-require');
const React = require('react');
mock('lottie-react-web', () => React.createElement('div', { 'data-testid': 'fake-lottie' }));
  1. 启动mocha时指定加载启动脚本:
mocha --require test/setup.js 'test/**/*.test.tsx'

内容的提问来源于stack exchange,提问作者M_Zarnowski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.12 05:09:01