简体   繁体   中英

Use Mock HTTP with Protractor and Jasmine

How can I use Mock HTTP with Jasmine and Protractor ?

In my test.spec.js , I declared a mock, but this mock doesn't work. I don't have any error. My api always responds and not the mock.

I never see 'mockModule!' in my console. My function is never executed :

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!')});
    });
});

In my app.js I don't have "ngMock".

I added this in my index.html :

node_modules/angular-mocks/angular-mocks.js

I run the test from the command prompt with 'gulp protractor-local':

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

All tests are ok, but not the mock.

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",
  }
}

I also had the same problem, and I resolved it creating a wrapper module with all mocks

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

And change the directive data-ng-app in the index file to mockBackend module

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

You can configure a gulp/grunt task to include this module and change the data-ng-app before run your tests.

In this link you can see a complete example: http://blog.xebia.com/angularjs-e2e-testing-using-ngmocke2e/

First thing you are mixing E2E testing and jasmine unit testing. For E2E testing using protractor.

Also make sure you have included your test file path in karma config for jasmine unit testing.

Make sure Selenium webdriver-manager is uptodate

eg

Snippet html for login page.

<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>

Protractor js for this html

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');
    })
});

protractor config

add following line

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

port will be change as per your config.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM