我正在开发REST API的前端。我使用Protractor进行端到端测试,并且模拟了API,因为我希望能够单独测试前端。
这是一个简单的测试:
describe('partner', function () {
it('should list partners', function () {
var page = new PartnerListPage();
var httpBackendMock = function () {
angular.module('httpBackendMock', ['ngMockE2E'])
.run(function ($httpBackend) {
$httpBackend.whenGET('/api/partners').respond(200, {
_embedded: {
partners: [
{
firstName: 'Elnur',
lastName: 'Abdurrakhimov'
}
]
}
});
$httpBackend.whenGET(/.*/).passThrough();
});
};
browser.addMockModule('httpBackendMock', httpBackendMock);
page.open();
expect(page.isOpen()).toBeTruthy();
expect(page.getPartner(0).firstName).toBe('Elnur');
expect(page.getPartner(0).lastName).toBe('Abdurrakhimov');
});
});
它的作用基本上是创建一个后端的模拟,以便它返回我想要的东西。
除了一件事,它一切都很美好。我希望能够在测试结束时调用以下方法:
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
我想这样做的原因是验证模拟是否获得了预期的请求。它对我提供的测试没有多大意义,但是我想说我想验证当我提交某个表单时,特定数据的特定POST
请求正在进行中执行。我想对后端模拟本身进行验证,以便我的测试与输出POST
请求的响应结果隔离,因为它将在另一个测试中进行测试。
如何访问我$httpBackend
添加到httpBackendMock
的{{1}}实例中使用的browser
个实例?
据我了解,Protractor和应用程序本身在不同的进程中运行。因此,我无法像在单元测试中那样直接访问$httpBackend
。
答案 0 :(得分:3)
您的应用程序在一个单独的进程中在浏览器和量角器中执行。所以你是对的,你无法直接访问浏览器上下文。
幸运的是,量角器为execute javascript in the browser提供了一种机制。我想你可以使用这种机制来访问$httpBackendMock
。
browser.executeAsyncScript(function() {
var $httpBackend = angular.injector(['httpBackendMock']).get('$httpBackend');
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});
注意:代码改编自this answer。
另一种选择可能是公开"检查网址"
$httpBackend.whenGET('/api/check').respond(function() {
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
return [200];
});
并在测试中使用它:
browser.get('/api/check');
答案 1 :(得分:0)
您应该尝试在量角器测试中避免使用httpBackend存根。它可以在以后更改您的测试数据,这比需要的更复杂。 Protractor有一个很好的替代mockHttp,那就是Protractor#addMockModule。您可以使用它来模拟单个模块以使其返回所需的结果。在调用Protractor#get()之前,需要添加此代码。如果它与现有服务具有相同的名称,它将在应用程序服务覆盖后加载。
您可以按如下方式使用它:
var dataUtilMockModule = function () {
// Create a new module which depends on your data creation utilities
var utilModule = angular.module('dataUtil', ['platform']);
// Create a new service in the module that creates a new entity
utilModule.service('EntityCreation', ['EntityDataService', '$q', function (EntityDataService, $q) {
/**
* Returns a promise which is resolved/rejected according to entity creation success
* @returns {*}
*/
this.createEntity = function (details,type) {
// This is your business logic for creating entities
var entity = EntityDataService.Entity(details).ofType(type);
var promise = entity.save();
return promise;
};
}]);
};
browser.addMockModule('dataUtil', dataUtilMockModule);
您可以将此运行作为测试之前设置的一部分,然后通过调用Protractor#clearMockModules()来清除模拟模块列表,为后续部分返回默认值,为下一次设置做好准备。
答案 2 :(得分:0)
我找到了比使用$httpBackend
方式更好的解决方案。
由于您在Node.js上运行Protractor测试,因此使用一些Node.js包来模拟后端更有意义,而不是我在问题中提出的这个丑陋和hacky解决方案。
Hock对我很有用,因此我建议使用它或类似的东西。