2015-03-31 87 views
4

我试图模拟对量角器测试中API调用的响应。在不同的测试中(以及在测试中),应用程序将发布POST到不同的POST数据并期待不同的响应的API(始终是相同的URL)。如何在量角器测试中的httpBackendMocks之间切换

具体而言,它是一个搜索引擎,我发送不同的查询并期待不同的结果。我有它成功的工作像下面的代码,但它越来越难以管理:

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

这有两个问题。

1)它不起作用。在清除并添加第二个模拟之后,​​仅显示第二个模拟,但是看起来第一个模拟仍在使用,基于expect和使用browser.pause()与ChromeDriver进行手动检查。看起来,如果没有至少重新加载页面,你不能改变模拟。

2)即使它工作,每个模拟模块都有大量的重复代码,因为它必须设置所有内容,包括passThrough()

如果我可以将所需的响应传递到我添加的模拟中,会更好的,但是我尝试过,并且在angular.module范围内传递给我自己的函数的任何东西都不可用。我能想到的唯一方法就是创建另一个带有提供程序的角度模块,该提供程序具有一个可以跟踪所需响应的变量,并将其注入到模拟模块中。我还没有尝试过,但它似乎是一个不必要的复杂解决方案。

回答

3

量角器中的模块模块基本上是在每次完整页面刷新时执行到浏览器中的代码。这是一种机制,可以让您自己省却麻烦,因为这样的刷新可以完全清除浏览器的状态(当然,Cookie除外)。正如你已经发现的那样,直到你触发这样的刷新(使用browser.get()),你的模块将永远不会执行。如果需要,您可以使用browser.executeScript()手动执行此操作。

关于从嘲笑你的后端随之而来的混乱 - 我采取了以下做法: 对后端默认模拟实现,同时也使很容易克服的,并用初始化函数每次测试前对其进行注册:

嘲笑,后端-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区块中:

模仿后端特殊用户。JS

exports.httpBackendMock = function() { 
    angular.module('httpBackendMockSpecialUser', []).run(function (httpBackendMockBase, testFixture) { 
     httpBackendMockBase.getLoginAuthenticated.respond(function() { 
      return [200, testFixture.specialUser, {}]; 
     }); 
    }); 
}; 

testFixture是保存我们的数据和嘲笑,后端基之前登记了另一个模块:

fixture.js

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); 
+0

“正如你已经发现的那样,直到你触发这样的刷新(使用browser.get()),你的模块才会被执行。”谢谢! – chromaloop 2015-06-01 17:56:10

+0

似乎每次你做一个browser.get(),你必须事先做另一个browser.addMockModule,因为如果你改变了URL,mocks就停止工作。 – 2016-08-03 18:07:41

+0

不应该如此。这样做会打破模块模块的目的。 – 2016-08-04 11:58:50