作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我试图在 Protractor 测试中模拟对 API 调用的响应。在不同的测试中(以及在测试中),应用程序将 POST 到一个 API(总是相同的 URL),并发布不同的数据,并期待不同的响应。
具体来说,它是一个搜索引擎,我发送不同的查询并期望返回不同的结果。我让它像下面的代码一样成功运行,但它变得难以管理:
var httpBackendMock = function() {
angular.module('httpBackendMock', ['ngMockE2E'])
.run(function($httpBackend) {
$httpBackend.whenPOST('//search_endpoint').respond(function(method, url, query, headers) {
query = JSON.parse(query);
if (query.bla = 'foo') {
var results = {... lots of json ...};
} else if (query.bla = 'bar') {
var results = {... lots of json ...};
} else if (query.something.else != 'whatever') {
var results = {... lots of json ...};
... etc ...
} else {
var results = {... lots of json ...};
}
return [200, results];
});
$httpBackend.whenGET(/.*/).passThrough();
})
};
beforeEach(function(){
browser.addMockModule('httpBackendMock', httpBackendMock);
});
beforeEach
并在需要时添加模拟,如下所示:
it('paginates', function(){
// mocking a search with 13 results, showing 10 results per page
browser.addMockModule('search_results', <some function>);
$('#searchbox').sendKeys('some keyword search');
$('#searchbutton').click();
expect($('#results li').count()).toEqual(10);
browser.clearMockModules();
browser.addMockModule('search_results_page2', <some other function>);
$('#next').click();
expect($('#results li').count()).toEqual(3)
});
getRegisteredMockModules()
仅显示第二个模拟,但似乎第一个模拟仍在使用,基于
expect
s和使用时的人工检查
browser.pause()
与 ChromeDriver。似乎您至少不重新加载页面就无法更改模拟。
passThrough()
.
angular.module
中都不可用。范围。我能想到的唯一方法是创建另一个带有提供者的 Angular 模块,该提供者具有一个变量,可以跟踪所需的响应,并将其注入(inject)到模拟模块中。我还没有尝试过,但这似乎是一个不必要的复杂解决方案。
最佳答案
Protractor 中的模拟模块基本上是在每次整页刷新时在浏览器中执行的代码。这是一种为您省去自己做这件事的麻烦的机制,因为这样的刷新完全清除了浏览器的状态(当然 cookie 除外)。正如您已经发现的那样,在您触发这样的刷新(使用 browser.get()
)之前,您的模块永远不会执行。您可以使用 browser.executeScript()
手动执行此操作如果你想。
关于 mock 后端带来的困惑 - 我采取了以下方法:
为您的后端提供一个默认的模拟实现,同时使其易于覆盖并在每次测试之前使用 init 函数注册它:
模拟后端base.js
exports.httpBackendMockBase = function () {
var exposeBackendCalls = function ($httpBackend) {
this.getLoginAuthenticated = $httpBackend.whenGET(/login\/authenticated.*/);
this.getFindStuff = $httpBackend.whenGET(/lookup\/findStuff.*/);
this.getFullProfile = $httpBackend.whenGET(/api\/full.*/);
};
angular.module('httpBackendMockBase', ['myClientApp', 'ngMockE2E'])
.service('httpBackendMockBase', exposeBackendCalls)
.run(function (httpBackendMockBase, testFixture) {
httpBackendMockBase.getLoginAuthenticated.respond(function () {
return [200, null, {}];
});
httpBackendMockBase.getFindStuff.respond(function () {
return [200, { stuff: testFixture.stuff }, {}];
});
httpBackendMockBase.getFullProfile.respond(function () {
return [200, { profile: testFixture.fullProfile }, {}];
});
});
};
afterEach
中删除它堵塞:
exports.httpBackendMock = function() {
angular.module('httpBackendMockSpecialUser', []).run(function (httpBackendMockBase, testFixture) {
httpBackendMockBase.getLoginAuthenticated.respond(function() {
return [200, testFixture.specialUser, {}];
});
});
};
testFixture
来自另一个模块,该模块保存我们的数据并在
之前注册模拟后端库 :
exports.data = {
stuff: null,
fullProfile: {},
specialUser: {}
};
exports.module = function (data) {
angular.module('backendFixture', []).constant('testFixture', data);
};
var fixtureModule = require('fixture');
var baseMockedBackend = require('mocked-backend-base');
browser.addMockModule('backendFixture', fixtureModule.module, fixtureModule.data);
browser.addMockModule('httpBackendMockBase', baseMockedBackend.httpBackendMockBase);
关于angularjs - 如何在 Protractor 测试中在 httpBackendMocks 之间切换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29377619/
我是一名优秀的程序员,十分优秀!