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

Webpack v4升级v5后Karma测试重复执行,如何保留外部依赖?

Webpack v5升级后Karma测试重复执行4次的解决方案

问题背景

将Webpack从v4升级到v5后,Karma测试会重复执行4次(v4版本中仅执行1次)。经排查,问题根源在于Karma配置的files数组——保留前5个included: true的全局依赖文件时,测试重复执行;移除这些文件后测试仅执行1次,但这些依赖是PHP SSR应用的必需项,测试无法脱离它们运行。

关键配置冲突

原Karma的files配置中,前5个全局依赖文件均设置included: true,同时测试入口文件modern.testContext.js也设置了included: true:

config.set({
    files: [
        {
            pattern: "public/dist/js/global/knockout-bundle.min.js",
            watched: false,
            included: true,
        },
        {
            pattern: "node_modules/jquery/dist/jquery.min.js",
            watched: false,
            included: true,
        },
        {
            pattern: "public/dist/js/global/portal.min.js",
            watched: false,
            included: true,
        },
        {
            pattern: "public/dist/js/global/foundation.min.js",
            watched: false,
            included: true,
        },
        {
            pattern: "public/dist/js/models/user.min.js",
            watched: false,
            included: true,
        },
        {
            pattern: "js/tests/unit/modern.testContext.js",
            watched: false,
            included: true,
        },
        // 图片资源配置...
    ],
})

同时Webpack测试配置已声明externals:

externals: {
    moment: "moment",
    jquery: "jQuery",
    knockout: "ko",
},

解决方案

问题核心是多个included: true的JS文件会被Karma依次注入测试页面,每个文件加载完成后都可能触发测试初始化,导致重复执行。结合Webpack的externals配置,可通过以下方式解决:

方案1:调整依赖加载方式,统一由测试入口控制

修改Karma的files配置,将前5个依赖的included改为false,保留served: true(确保文件可被访问):

files: [
    {
        pattern: "public/dist/js/global/knockout-bundle.min.js",
        watched: false,
        included: false,
        served: true,
    },
    {
        pattern: "node_modules/jquery/dist/jquery.min.js",
        watched: false,
        included: false,
        served: true,
    },
    {
        pattern: "public/dist/js/global/portal.min.js",
        watched: false,
        included: false,
        served: true,
    },
    {
        pattern: "public/dist/js/global/foundation.min.js",
        watched: false,
        included: false,
        served: true,
    },
    {
        pattern: "public/dist/js/models/user.min.js",
        watched: false,
        included: false,
        served: true,
    },
    {
        pattern: "js/tests/unit/modern.testContext.js",
        watched: false,
        included: true,
    },
    // 图片资源配置...
],

在测试入口文件modern.testContext.js顶部,按依赖顺序动态加载这些文件:

// 动态加载脚本工具函数
const loadScript = (src) => {
    return new Promise((resolve, reject) => {
        const script = document.createElement('script');
        script.src = `/base/${src}`;
        script.onload = resolve;
        script.onerror = reject;
        document.head.appendChild(script);
    });
};

// 按依赖顺序加载全局文件
(async () => {
    await loadScript('node_modules/jquery/dist/jquery.min.js');
    await loadScript('public/dist/js/global/knockout-bundle.min.js');
    await loadScript('public/dist/js/global/portal.min.js');
    await loadScript('public/dist/js/global/foundation.min.js');
    await loadScript('public/dist/js/models/user.min.js');

    // 原有测试导入逻辑
    const importAll = (r) => {
        r.keys().forEach(r);
    };
    importAll(require.context("./modern/features", true, /\.(spec|test)\.js$/));
    importAll(require.context("./modern/main", true, /\.(spec|test)\.js$/));
})();

方案2:合并全局依赖为单个bundle

将5个全局依赖合并为一个单独的vendor-bundle.js(可通过Webpack或其他打包工具实现),在Karma的files中仅注入这个合并后的bundle(included: true),测试入口文件仍保留included: true。合并后的vendor文件不会触发测试执行,仅测试入口会触发一次测试初始化。

方案3:使用Karma插件管理npm依赖

对于jquery、knockout这类npm包,可使用对应Karma插件(如karma-jquery、karma-knockout),将其加入Karma的frameworks数组,替代手动在files中配置:

// 在karma.default.conf.js中修改frameworks
frameworks: ["mocha", "chai", "sinon", "webpack", "jquery", "knockout"],

自定义的portal.min.js等文件仍可采用方案1的方式处理。

原理说明

Webpack v5与Karma的集成逻辑发生了变化:当多个included: true的JS文件被注入时,每个文件的加载都会触发测试初始化流程,导致重复执行。而Webpack v4中不存在此触发逻辑,因此仅执行一次。通过将依赖设为served: true但included: false,我们让依赖仅被服务器托管,而非自动注入页面,由测试入口统一控制加载时机,确保仅触发一次测试执行。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 10:46:57