【问题标题】:Protractor with Angular Mocks Throws "Window Not Defined"带角度模拟的量角器抛出“未定义窗口”
【发布时间】:2017-02-22 01:38:48
【问题描述】:

我在这个问题上搜索了很多,但找不到解决方案。

我正在尝试模拟我的后端,该后端经过了很好的测试,因此我可以完全隔离我的前端。我尝试过使用 protractor-http-mock 以及 angular-mocks 的各种努力。

使用 HttpBackend 确定了 angular-mocks 方法后,我在启动量角器测试时遇到了这个错误:

MBP:test-site admin$ protractor protractor.conf.js
Using ChromeDriver directly...
[launcher] Running 1 instances of WebDriver
[launcher] Error: ReferenceError: window is not defined
    at Object.<anonymous> (/Users/Ed/Sites/F4F/web/node_modules/angular/angular.js:30426:4)
    at Module._compile (module.js:413:34)
    at Object.Module._extensions..js (module.js:422:10)
    at Module.load (module.js:357:32)
    at Function.Module._load (module.js:314:12)
    at Module.require (module.js:367:17)
    at require (internal/module.js:16:19)
    at Object.<anonymous> (/Users/Ed/Sites/F4F/web/node_modules/angular/index.js:1:1)
    at Module._compile (module.js:413:34)
    at Object.Module._extensions..js (module.js:422:10)
[launcher] Process exited with error code 100

这是我的 protractor.conf.js

exports.config = {

    directConnect: true,

    // Capabilities to be passed to the webdriver instance.
    capabilities: {
        'browserName': 'chrome'
    },

    chromeOnly: true,
    chromeDriver: './node_modules/protractor/selenium/chromedriver',

    // Framework to use. Jasmine 2 is recommended.
    framework: 'jasmine2',

    baseUrl: 'http://localhost:5000/',
    seleniumAddress: 'http://127.0.0.1:4444/wd/hub',

    // Spec patterns are relative to the current working directly when
    // protractor is called.
    specs: ['./tests/**/*.js'],

    // Options to be passed to Jasmine.
    jasmineNodeOpts: {
        showColors: true,
        defaultTimeoutInterval: 30000
    }

};

这是我的测试:

'use strict'

var angular         = require('angular');
var angular_mock    = require('angular-mocks');
var HttpBackend     = require('httpbackend');
var backend         = null;

describe("Footer", function () {

    beforeEach(function() {
        backend = new HttpBackend(browser);
    });

    afterEach(function() {
        backend.clear();
    });

    describe("Display Values", function () {

        it("should show correct contact details", function () {

            backend.whenGET(/app/).respond({
                "name": "ExampleApp",
                "company": {
                    "code": "EXA",
                    "name": "ExampleApp",
                    "brand_name": "ExampleApp",
                    "head_office_id": 3,
                    "display_email": "sales@example.com",
                    "display_tel": "+44 (0) 1234 56789"
                }
            });

            browser.get('/');

            var tel_li      = $('#footer .top li:first-child');
            var email_li    = $('#footer .top li:last-child');

            expect(tel_li.getText()).toEqual('+44 (0) 1234 56789');
            expect(email_li.getText()).toEqual('sales@example.com');

        });
    });
});

有人可以帮忙吗?

--- 回复@alecxe 的评论

将测试修改为如下所示:

'use strict'

describe("Footer", function () {

    describe("Display Values", function () {

        it("should show correct contact details", function () {

            browser.get('/');

        });
    });
});

给出以下结果:

MBP:test-site admin$ protractor protractor.conf.js
Using ChromeDriver directly...
[launcher] Running 1 instances of WebDriver
Started
.


1 spec, 0 failures
Finished in 0.749 seconds
[launcher] 0 instance(s) of WebDriver still running
[launcher] chrome #1 passed

【问题讨论】:

  • 听起来像是应用程序本身的问题:如果您转到 http://localhost:5000/ 怎么办 - 您是否看到应用程序已加载并且控制台上没有错误?
  • 是的!在测试之外,应用程序运行良好。这个 http 调用是通过 UI-Router 完美解决的。我可以正常使用该应用程序。我已经开发了它,现在我回来在部署之前编写测试。我知道这很淘气,但是......
  • 我也在整个应用程序中搜索了名为“window”的松散变量,但没有出现任何结果。
  • 好的,如果你从测试中删除所有的需求和模拟,只留下browser.get() - 它现在是否通过而没有错误?谢谢!
  • @alecxe 我会把修改后的测试放在上面最后一段的下面。

标签: javascript angularjs protractor httpbackend angular-mock


【解决方案1】:

根本不要导入angular-mocksangularhttpbackend 不需要导入它们:

'use strict'

var HttpBackend     = require('httpbackend');
var backend         = null;

describe("Footer", function () {

    beforeEach(function() {
        backend = new HttpBackend(browser);
    });

    afterEach(function() {
        backend.clear();
    });

    describe("Display Values", function () {

        it("should show correct contact details", function () {

            backend.whenGET(/app/).respond({
                "name": "ExampleApp",
                "company": {
                    "code": "EXA",
                    "name": "ExampleApp",
                    "brand_name": "ExampleApp",
                    "head_office_id": 3,
                    "display_email": "sales@example.com",
                    "display_tel": "+44 (0) 1234 56789"
                }
            });

            browser.get('/');

            var tel_li      = $('#footer .top li:first-child');
            var email_li    = $('#footer .top li:last-child');

            expect(tel_li.getText()).toEqual('+44 (0) 1234 56789');
            expect(email_li.getText()).toEqual('sales@example.com');

        });
    });
});

【讨论】:

  • 我确实复制并粘贴了您的代码,但它仍然抛出与第一次提到的完全相同的错误..
  • 如果我删除 require("angular"),错误会从 "Error: ReferenceError: window is not defined" 变为 "Error: [$injector:nomod] Module 'ngMockE2E' is not available!",这肯定意味着我们需要包含 anuglar-mocks?
  • @EdStephenson 我认为应该加载angular-mocks 的是您的被测应用程序,而不是您的测试本身。而且,您也不需要在测试中导入 angular。
  • 包含 'ngMockE2E' 会导致整个应用程序在测试和正常运行时都失败。正常运行时,每个 $http 调用都会出现"Error: Unexpected request: GET" 错误。测试再次失败并出现“ReferenceError:未定义窗口”。我还尝试使用包含“ngMockE2E”的测试的 beforeEach 部分模拟模块,但失败并显示“Unexpected”。错误。大概来自“angular.module(”元素,虽然它没有给出意外点在哪里的清晰图片。我很难理解这怎么这么难……!
【解决方案2】:

我遇到了你的确切问题,最终通过将angular-mocks 作为原始字符串导入并通过browser.addMockModule 注入来解决它:

const fs = require('fs');
const ngMock = fs.readFileSync(__dirname + '/../../node_modules/angular-mocks/angular-mocks.js', 'utf-8');

browser.addMockModule('ngMockE2E', ngMock);
browser.addMockModule('e2e', function e2e() {
  angular.module('e2e', ['ngMockE2E'])
    .run(['$httpBackend', function($httpBackend) {
      // Your mocked calls here
    }])
});

这将强制驱动程序在运行时编译脚本,window 可用。但是,如果您有 browser.ignoreSynchronization = true;,这将中断。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-10-31
    • 2015-03-28
    • 2018-10-25
    • 1970-01-01
    • 2014-10-15
    • 2016-03-01
    • 1970-01-01
    • 2015-03-02
    相关资源
    最近更新 更多