【问题标题】:Use Mock HTTP with Protractor and Jasmine将 Mock HTTP 与 Protractor 和 Jasmine 一起使用
【发布时间】:2015-11-24 12:58:08
【问题描述】:

如何将 Mock HTTP 与 Jasmine 和 Protractor 一起使用?

在我的 test.spec.js 中,我声明了一个模拟,但这个模拟不起作用。我没有任何错误。我的 api 总是响应而不是模拟。

我从未见过“mockModule!”在我的控制台中。 我的函数永远不会执行:

browser.addMockModule('modName', function() {

    browser.executeScript(function() {console.log('mockModule!')});

    angular.module('modName', []).value('foo', 'bar').run(function ($httpBackend) {
    $httpBackend.whenPOST('http://api.webapp.net/app_dev.php/module/search?direction=asc&page=1').respond('repsond');

    browser.executeScript(function() {console.log('enter mockModule!')});
    });
});

在我的 app.js 中,我没有“ngMock”。

我在 index.html 中添加了这个:

node_modules/angular-mocks/angular-mocks.js

我使用“gulp protractor-local”从命令提示符运行测试:

gulp.task('protractor-local', shell.task([
        'protractor protractor.conf.js --baseUrl="http://mywebapp.local.net"'
]));

所有测试都可以,但不是模拟。

test.spec.js

var loginPO = new(require('./models/login.model.js'))();

describe("hello", function() {

    it("I click on the button-search button", function() {

        loginPO.wait(10);

        //browser.ignoreSynchronization = false;

        browser.addMockModule('modName', function() {

            browser.executeScript(function() {console.log('mockModule!')});

            angular.module('modName', []).value('foo', 'bar').run(function ($httpBackend) {
                $httpBackend.whenPOST('http://api.webapp.net/app_dev.php/module/search?direction=asc&page=1').respond('repsond');

                browser.executeScript(function() {console.log('enter mockModule!')});
            });
        });

        //browser.getRegisteredMockModules();

        loginPO.clickButtonSearchButton();
        loginPO.wait(10);
    });

    it("I am on the home page", function() {
        loginPO.visit('#/');
    });

    ...

});

models/login.model.js

'use strict';

var _ = require('lodash');

var LoginPageObject = function() {

    var signInButton = element(by.id('signIn'));

    _.mixin(this, require('./common/base.js').Base);

    this.path = '#/';

    this.clickButtonSearchButton = function() {
        return browser.driver.findElement(by.id('button-search')).click();
    };

    ...

};

module.exports = LoginPageObject;

common/base.js

function visit(path, params) {
    return browser.get(this.path + (params || ''));
}

function wait(params) {
    params = params * 1000;
    return browser.sleep(params);
}
...

exports.Base = {
    visit: visit,
    wait: wait,
    ...
};

protractor.config.js

exports.config = {
  directConnect: true,

  seleniumServerJar: 'node_modules/selenium-server/lib/runner/selenium-server-standalone-2.48.2.jar',

  specs: [
    'jasmine/*.spec.js'
  ],

  getPageTimeout: 30000,

  capabilities: {
    'browserName': 'chrome',
    version: '',
    platform: 'ANY'
  },

  framework: 'jasmine2'

};

** karma.conf.js **

// Karma configuration

module.exports = function(config) {

    var configuration = {

        basePath: './',

        frameworks: [
            'jasmine-jquery',
            'jasmine',
            'jasmine-matchers'
        ],

        files: [
            ...
            'assets/libs/angularjs/angular.min.js',
            'node_modules/angular-mocks/angular-mocks.js',
            ...
            'assets/libs/angularjs/sweetalert.min.js',
            'assets/libs/angularjs/ui-bootstrap-tpls.min.js',
            'app/app.js',
            'app/*/*.js',
            'app/*/*/*.js',
            'app/*/*/*/*.js',
            {
                pattern: 'app/*/*/*/*/*.json',
                included: false
            }
        ],

        exclude: [],

        preprocessors: {
            'app/**/!(*.test).js': ['coverage']
        },

        coverageReporter: {
            type: 'text',
            dir: 'coverage/'
        },

        reporters: ['spec'],

        port: 8080,

        colors: true,

        logLevel: config.LOG_INFO,

        autoWatch: false,

        browsers: ['PhantomJS'],

        singleRun: true,

        customLaunchers: {
            'PhantomJS_custom': {
                base: 'PhantomJS',
                    options: {
                        windowName: 'my-window',
                        settings: {
                        webSecurityEnabled: false
                    }
                },
                flags: ['--load-images=true'],
                debug: true
            }
        },

        phantomjsLauncher: {
            exitOnResourceError: true
        }
    };

    config.set(configuration);
};

package.json

{
  "name": "webapp",
  "version": "1.0.0",
  "description": "webapp",
  "dependencies": {
    "angular-mocks": "^1.4.5",
    "chromedriver": "^2.19.0",
    "gulp-protractor": "^1.0.0",
    "gulp-shell": "^0.5.0",
    ...
    "protractor": "^2.5.1",
    "selenium-server": "^2.48.2",
    "selenium-standalone": "^4.7.0",
    "selenium-webdriver": "^2.48.0",
  }
}

【问题讨论】:

  • 您是从浏览器还是命令提示符运行?
  • 我从命令提示符运行测试: protractor protractor.conf.js --baseUrl="mywebapp.local.net"
  • 另外请分享 KARMA 配置文件
  • Karma 运行 phamtomjs 并执行我的单元测试。
  • 还有一个为什么需要带量角器的 ngMock?我们使用 ngMock 与 jasmine 或其他进行单元测试,量角器是 E2E 测试框架。不需要带量角器的 ngMock

标签: javascript angularjs jasmine protractor angularjs-e2e


【解决方案1】:

我也遇到了同样的问题,我通过创建一个包含所有模拟的包装模块解决了这个问题

  angular.module('mockBackend', ['myAppModule', 'ngMockE2E']).run(function ($httpBackend) {
    $httpBackend.when('GET', /user/).respond(200, {login: 'user_test'});
  });

并将索引文件中的data-ng-app指令改为mockBackend模块

<html data-ng-app='mockBackend'>

您可以配置 gulp/grunt 任务以包含此模块并在运行测试之前更改 data-ng-app。

在这个链接中你可以看到一个完整的例子:http://blog.xebia.com/angularjs-e2e-testing-using-ngmocke2e/

【讨论】:

  • 好主意!您是否在 httpbackend 中加载了 json 文件作为响应?
  • 我没有,但听起来很优雅!
  • 从 httpbackend 加载 JSON 文件,它适用于:stackoverflow.com/a/24287558/5453732
【解决方案2】:

首先要混合 E2E 测试和 jasmine 单元测试。 使用量角器进行 E2E 测试。

还要确保您已在 karma 配置中包含测试文件路径以进行 jasmine 单元测试。

确保Selenium webdriver-manager 是最新的

例如

登录页面的 html 片段。

<div class="form-group" 
             ng-class=" {'has-error' :!loginForm.userEmail.$pristine && loginForm.userEmail.$invalid}" >
            <label for="email">Enter Email</label>
            <input  type="email" name="userEmail"   class="form-control" required  placeholder="Enter Email" ng-model="objUser.userEmail">        
            <div ng-show="loginForm.userEmail.$touched || loginForm.$submitted">
                <span ng-show="loginForm.userEmail.$error.required">Please enter valid email</span>
                <span ng-show="loginForm.userEmail.$error.email">Please enter valid email</span>
            </div>
        </div>

这个 html 的量角器 js

describe("check user creation form integration", function() {

    var ptor,userEmail,userPassword;
    beforeEach(function(){
        ptor = protractor.ExpectedConditions;
        userEmail       = element(by.model("objUser.userEmail"));
    });

    it("\n\n1 . check login functionality",function(){

        browser.get("/#/");
        userEmail.sendKeys("*^*");
        expect(userEmail.getAttribute("class")).toContain('ng-invalid');
         userEmail.clear();
        browser.sleep(2000);
        userEmail.sendKeys("HJJHJH");
        expect(userEmail.getAttribute("class")).toContain('ng-valid');
    })
});

量角器配置

添加以下行

exports.config = {
  baseUrl: 'http://localhost:3000/'
};

端口将根据您的配置进行更改。

【讨论】:

  • 我不明白。我使用 karma+jasmine 运行我的单元测试(使用“karma start”,我使用 protractor+jasmine 运行我的端到端测试(使用“protractor protractor.conf.js --baseUrl="mywebapp.local.net" ")。对我来说,业力和量角器之间没有桥梁。
  • protractor E2E测试不需要运行karma,可以通过protractor命令运行
  • 是的,我知道,我不使用量角器,只有量角器
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多