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

如何在Jest测试DOM中渲染Module Federation远程组件?

如何在Jest+React Testing Library中实际渲染Module Federation组件进行测试

我正在为React.js应用编写Jest测试,使用React Testing Library。应用中导入了Module Federation组件,需要找到实际渲染这些联邦组件的测试方法,不能仅mock它们,因为需要验证测试DOM中的真实渲染结果。

我参考了Zack Jackson的《Federated Unit Tests?!》视频建议,但不知道如何在项目中落地实现。


我的测试代码

describe('DropDown Selector Tests', () => {
    test('Should render all passed-in dropdowns', () => {
        render(<DropDownContainer dropdowns={dropdowns} />);       
        screen.debug(); // 打印DOM树
        dropdowns.forEach((drop_down, index) => {
            const element = screen.getByTestId(`dropdown-select-${index}`);
            expect(document.body.contains(element)).toBe(true);

            const firtItem: DropdownSelectItemProps = drop_down.items[0] as DropdownSelectItemProps
            const firstLabelText: string = firtItem.label as string; 
            const dropDown = screen.getByLabelText(firstLabelText);
            expect(document.body.contains(dropDown)).toBe(true);
        });
    });
})

import React, { ReactElement } from 'react';
import {
    DropdownSelect,
    DropdownSelectProps
} from 'federated/Components';
import './DropDownContainer.scss';

export interface DropDownContainerProps {
    /** 下拉列表集合 */
    dropdowns: DropdownSelectProps[]
}

/**
 * 接收下拉列表集合,在响应式容器中组织展示
 * @param props
 * @returns
 */
const DropDownContainer = (props: DropDownContainerProps) => {
    const { dropdowns } = props;

    return (
        <div className='sort-container' data-testid='dropdown-container'>                   
            {
                dropdowns.map((d, index) => {
                    return (
                        <div data-testid={`dropdown-select-${index}`} key={index} >
                            <DropdownSelect                                  
                                key={index}
                                className='sort'
                                {...d} />
                        </div>
                    )
                })
            }
        </div>
    )
}

export default DropDownContainer;

测试渲染的DOM结果

<body>
  <div>
    <div
      class="sort-container"
      data-testid="dropdown-container"
    >
      <div
        data-testid="dropdown-select-0"
      />
      <div
        data-testid="dropdown-select-1"
      />
      <div
        data-testid="dropdown-select-2"
      />
      <div
        data-testid="dropdown-select-3"
      />
    </div>
  </div>
</body>

可见DropdownSelect组件并未被渲染。正常渲染时,组件DOM应该如下:


预期正常渲染的DOM结构

<div class="sort-container">
<div id="sui-dropdown-select-0" class="sui-dropdown-select sort" aria-label="sui-dropdown-select-0">
Sale Type:<select style="display: none;">
        <option id="Sale Type1" value="Sale Type1">Sale Type1</option>
        <option id="Sale Type2" value="Sale Type2">Sale Type2</option>
    </select>
    <div class="sui-dropdown-select-nice-select sui-dropdown-select-right">
        <span class="sui-dropdown-select-current">Show All</span>
    </div>
</div>
<div id="sui-dropdown-select-1" class="sui-dropdown-select sort" aria-label="sui-dropdown-select-1">
Market:<select style="display: none;">
        <option id="West" value="West">West</option>
        <option id="East" value="East">East</option>
    </select>
</div>

Webpack配置

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
const { FederatedTypesPlugin } = require('@module-federation/typescript');
const { ModuleFederationPlugin } = webpack.container;
const federationConfig = require('./federationConfig');
const package = require('../package.json');
const { NativeFederationTestsHost, NativeFederationTestsRemote } = require('@module-federation/native-federation-tests/webpack');

// 根据开发/生产环境设置homepage
const homepage = process.env.HOMEPAGE ?? `/${(package.homepage ?? '')}`.replace("//", "/");

module.exports = {
  experiments: { topLevelAwait: true },
  entry: {
    main: path.join(__dirname, '../src/index.ts'),
  },
  module: {
    rules: [
        // 内联SVG资源
        {
            test: /\.svg/,
            type: 'asset/inline'
          },
        // 加载TypeScript文件
        {
            test: /\.(js|jsx|tsx|ts)$/,
            loader: 'ts-loader',
            exclude: /node_modules/,
        },
    ],
  },
  plugins: [
    new ModuleFederationPlugin(federationConfig),
    new FederatedTypesPlugin({
      federationConfig,
    }),
    new HtmlWebpackPlugin({
      template: 'public/index.html',
        title: 'internalbilling',
      filename: 'index.html',
      chunks: ['main'],
        publicPath: homepage,
    }),
      new NativeFederationTestsRemote({ federationConfig }),
      new NativeFederationTestsHost({ federationConfig })
  ],
  resolve: {
    extensions: ['.tsx', '.ts', '.jsx', '.js', '.json'],
  },
};

federationConfig配置

const dependencies = require('../package.json').dependencies;

module.exports = {
    name: 'myapp'.toLowerCase(),
    remotes: {
        federated: `federated@https://media.CompanyA.com/cdn/js/CompanyAUI/remoteEntry.js`
    },
    filename: 'remoteEntry.js',
    shared: {
        ...dependencies,
        'react': {
            singleton: true,
            requiredVersion: dependencies['react'],
        },
        'react-dom': {
            singleton: true,
            requiredVersion: dependencies['react-dom'],
        },
    },
};

package.json中的Jest配置

"jest": {
  "preset": "ts-jest",
  "clearMocks": true,
  "collectCoverage": true,
  "coverageDirectory": "coverage",
  "moduleDirectories": [
    "node_modules",
    "@mf-types"
  ],
  "moduleFileExtensions": [
    "js",
    "mjs",
    "cjs",
    "jsx",
    "ts",
    "tsx",
    "json",
    "node"
  ],
  "moduleNameMapper": {
    "^companyA/Components/(.*)$": "./@mf-types/companyA/Components.d.ts"
  },
  "reporters": [
    "default"
  ],
  "rootDir": "./ClientApp",
  "testEnvironment": "jsdom",
  "globals": {
    "transform": {
      "^.\\.scss$": "jest-scss-transform",
      "^.\\.[t|j]sx?$": "babel-jest"
    },
    "verbose": true
  },
  "transform": {
    "^.+\\.scss$": "jest-scss-transform",
    "^.+\\.tsx?$": "ts-jest"
  },
  "setupFilesAfterEnv": [
    "<rootDir>/configs/jest.setup.ts"
  ]
}

已尝试的方法

  • 使用mock,但不符合需求,因为需要验证联邦组件的实际渲染结果
  • 尝试配置项目以渲染联邦组件,但未成功

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 02:14:57