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

无ngApp指令手动引导的Angular应用,Protractor addMockModule无法生效?

问题根源分析

你的问题核心在于Protractor的addMockModule是为Angular自动引导(通过ngApp指令)设计的,而手动引导的场景下,这个机制无法自动把mock模块注入到你的应用依赖中。

你看到inside httpBackendMock被打印,说明Protractor确实执行了mock模块的定义函数,但这个模块并没有被你的Angular应用引用——因为手动引导时,你是通过angular.bootstrap手动指定应用依赖模块的,而这些mock模块不在这个列表里,所以模块的run块永远不会被触发,自然无法拦截API请求。

解决方案

针对手动引导的Angular应用,我们需要让mock模块被包含到应用的依赖列表中,这里有两种可靠的实现方式:

方式一:在应用代码中预留测试模块注入入口

修改你的应用手动引导代码,增加一个测试环境下的入口,允许外部传入额外的mock模块:

// 你的应用手动引导代码(比如app.js)
var baseModules = ['myApp']; // 这里是你原本的应用主模块

// 仅在测试环境下加载额外mock模块
if (window.__PROTRACTOR_MOCK_MODULES__) {
  baseModules = baseModules.concat(window.__PROTRACTOR_MOCK_MODULES__);
}

// 手动引导应用
angular.bootstrap(document.body, baseModules);

然后在你的Protractor测试代码中,先把需要加载的mock模块名存入全局window对象,再加载页面:

var angularMocks = require('./angularMocks.module.js').mock;
browser.addMockModule("ngMockE2E", angularMocks );
browser.addMockModule('httpBackendMock', function httpBackendMock() {
    console.log('inside httpBackendMock');
    angular.module("httpBackendMock", ['ngMockE2E'])
        .run(['$httpBackend', function ($httpBackend) {
            console.log("Inside Run");
            $httpBackend.whenGET(/.*employees.*/).respond(404, '');
            $httpBackend.whenGET(/.*/).passThrough();
            $httpBackend.whenPOST(/.*/).passThrough();
            $httpBackend.whenPUT(/.*/).passThrough();
        }]);
});

// 在加载页面前,将mock模块名注入到全局变量
browser.executeScript(() => {
  window.__PROTRACTOR_MOCK_MODULES__ = ['ngMockE2E', 'httpBackendMock'];
});

browser.get(url);

这种方式的好处是不需要大幅改动测试代码,且生产环境下因为window.__PROTRACTOR_MOCK_MODULES__不存在,不会有任何影响。

方式二:在Protractor中手动引导应用并包含mock模块

如果不想修改应用代码,可以在Protractor中控制页面加载时机,手动完成应用的bootstrap,同时包含mock模块:

// 先加载页面(确保你的应用代码此时不会自动执行bootstrap,比如可以把bootstrap代码放到一个函数里,等待触发)
browser.get(url);

// 在浏览器上下文执行脚本,手动加载mock模块并引导应用
browser.executeAsyncScript((callback) => {
  // 加载Angular Mocks脚本(如果之前的addMockModule没生效,这里直接引入)
  const mockScript = document.createElement('script');
  mockScript.src = './angularMocks.module.js'; // 注意路径要和测试环境的资源路径匹配
  mockScript.onload = () => {
    // 定义httpBackendMock模块
    angular.module("httpBackendMock", ['ngMockE2E'])
      .run(['$httpBackend', ($httpBackend) => {
          console.log("Inside Run");
          $httpBackend.whenGET(/.*employees.*/).respond(404, '');
          $httpBackend.whenGET(/.*/).passThrough();
          $httpBackend.whenPOST(/.*/).passThrough();
          $httpBackend.whenPUT(/.*/).passThrough();
      }]);

    // 手动引导应用,包含主模块和mock模块
    angular.bootstrap(document.body, ['myApp', 'ngMockE2E', 'httpBackendMock']);
    callback();
  };
  document.body.appendChild(mockScript);
});

这种方式适合无法修改应用代码的场景,但需要确保应用代码没有提前自动执行bootstrap。

关键注意点
  • 确保angularMocks的路径在测试环境下可访问,避免404错误
  • 生产环境下要移除测试相关的全局变量判断,或者通过构建工具(比如Webpack、Angular CLI)的环境变量来控制,防止测试代码泄露到生产环境

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:59:48