将模拟 HTTP 与 Protractor 和 Jasmine 结合使用
Use Mock HTTP with Protractor and Jasmine
如何将 Mock HTTP 与 Jasmine 和 Protractor 一起使用?
在我的 test.spec.js 中,我声明了一个 mock,但是这个 mock 不起作用。我没有任何错误。我的 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",
}
}
首先,您要混合 E2E 测试和 jasmine 单元测试。
使用量角器进行 E2E 测试。
还要确保您已将测试文件路径包含在用于 jasmine 单元测试的 karma 配置中。
确保 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>
量角器 js 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');
})
});
量角器配置
添加以下行
exports.config = {
baseUrl: 'http://localhost:3000/'
};
端口将根据您的配置进行更改。
我也有同样的问题,我解决了它创建一个包含所有模拟的包装器模块
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。
在这个link你可以看到一个完整的例子:http://blog.xebia.com/angularjs-e2e-testing-using-ngmocke2e/
如何将 Mock HTTP 与 Jasmine 和 Protractor 一起使用?
在我的 test.spec.js 中,我声明了一个 mock,但是这个 mock 不起作用。我没有任何错误。我的 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",
}
}
首先,您要混合 E2E 测试和 jasmine 单元测试。 使用量角器进行 E2E 测试。
还要确保您已将测试文件路径包含在用于 jasmine 单元测试的 karma 配置中。
确保 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>
量角器 js 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');
})
});
量角器配置
添加以下行
exports.config = {
baseUrl: 'http://localhost:3000/'
};
端口将根据您的配置进行更改。
我也有同样的问题,我解决了它创建一个包含所有模拟的包装器模块
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。
在这个link你可以看到一个完整的例子:http://blog.xebia.com/angularjs-e2e-testing-using-ngmocke2e/