我现在有一个项目,我们需要暂时嘲笑后端服务器,并且我们在应用程序$httpBackend
功能上使用.run
。我需要对包含$httpBackend
的服务进行单元测试,因为我们将对我们将要覆盖的服务器进行大量模拟调用。所以现在这就是我所拥有的。作为我的问题的前言,当我从简单页面上的控制器调用mockDataService.getWorkflowTask
时,当前设置有效。
我的服务器更换服务:
angular.module('app').run(function ($httpBackend, $resource, FakeBackendService) {
// TODO: add all necessary http intercepts.
$httpBackend.whenGET('JSON file').respond(function (method, url, data) {
var request = new XMLHttpRequest();
request.open('GET', url, false);
request.send(null);
return [request.status, request.response, {}];
});
$httpBackend.whenGET(/.*/).respond(function (method, url, data) {
return [200, FakeBackendService.getWorkflowTasks(), {}];
});
});
以下是FakeBackendService
的服务:
(function () {
'use strict';
var injectParams = [];
function service(lodash) {
var vm = this;
var ret = {
getWorkflowTasks: getWorkflowTasks
};
function getWorkflowTasks() {
if (vm.workflowtasks.length < 1) {
vm.workflowtasks = loadWorkflowTasks("Some JSON file");
}
return vm.workflowtasks;
};
function loadWorkflowTasks(file) {
var workflowTasks = [];
var request = new XMLHttpRequest();
request.open("GET", file, false);
request.send(null);
if (request.status == 200) {
workflowTasks = angular.fromJson(request.response);
}
return workflowTasks;
};
function init() {
vm.workflowtasks = [];
}
init();
return ret;
}
service.$inject = injectParams;
angular.module('mock.FakeBackendService', []).service('FakeBackendService', service);
})();
所以这是目前的后端服务器替换模拟。以下是我的数据处理服务,其中包含对$http.get(blah blah blah)
的调用。
(function () {
'use strict';
var injectParams = ['$http', '$q', 'mockConfigService', '$httpBackend'];
function factory($http, $q, configService, $httpBackend) {
var vm = this;
var factory = {
getWorkflowTask: getWorkflowTask
};
function getWorkflowTask(str) {
return getResource(str);
}
function init() {
// Get the URL we will be using to get data from
vm.dataServiceURL = configService.getDataServiceURL();
}
function getResource(baseResource) {
var resource = vm.dataServiceURL + baseResource;
return $http.get(resource).then(function (response) {
if (typeof response.data == 'object') {
// Got valid response
return $q.resolve(response.data);
}
else {
// Invalid response
return $q.reject(response.data);
}
}, function (response) {
// Something went wrong
return $q.reject(response.data);
});
}
init();
return factory;
};
factory.$inject = injectParams;
angular.module('mock.dataService', []).factory('mockDataService', factory);
}());
现在进行Jasmine-Karma单元测试。
describe("HTTP Backend Mock testing", function () {
beforeEach(angular.mock.module("app"));
beforeEach(angular.mock.module("mock.FakeBackendService"));
beforeEach(angular.mock.module("mock.configService"));
beforeEach(angular.mock.module("mock.dataService"));
it("Get the workflow task", angular.mock.inject(function (mockDataService) {
var valid = "";
var promise = mockDataService.getWorkflowTask('http://localhost/foo');
promise.then(function (response) {
valid = "Success";
}, function (response) {
valid = "Failure";
});
expect(valid).toBe("Success");
}));
});
现在回答这个问题。所以,我首先要说的是我是AngularJS世界的新手,对Jasmine来说更是如此。无论如何,当我调试单元测试时,我发现承诺的状态仍然是0,我总是得到预期&#39;&#39;成功&#39;成功&#39;告诉我我永远不会解决(希望我使用正确的术语)来自$http
mockDataService
服务的承诺。我试过玩一些,试着看看有没有人以前做过这种事情。我发现了大量的例子,其中$httpBackend
在测试中被嘲笑但没有像我尝试的那样。任何想法或建议都会很棒。感谢。
EDIT获得了一个稍微有效的解决方案
所以我决定通过run()
服务,并在expectGET().respond()
中做同样的回复。
describe("HTTP Backend Mock testing", function () {
beforeEach(angular.mock.module("app"));
beforeEach(angular.mock.module("mock.FakeBackendService"));
beforeEach(angular.mock.module("mock.configService"));
beforeEach(angular.mock.module("mock.dataService"));
it("Get the workflow task", angular.mock.inject(function (mockDataService, $httpBackend, FakeBackendService) {
var valid = "";
$httpBackend.expectGET('http://server:80/api/foo').respond(200, FakeBackendService.getWorkflowTasks());
var promise = mockDataService.getWorkflowTask('foo');
promise.then(function (response) {
valid = "Success";
}, function (response) {
valid = "Failure";
});
$httpBackend.flush();
expect(valid).toBe("Success");
}));
});
这种方式解决了run()
的测试问题,因为目标是验证 1)正则表达式匹配调用正确的FakeBackendService
和 2) FakeBackendService
返回正确的文件并实际加载它。我想我可以通过模仿expectGET
中的相同正则表达式来做到这一点。但是,我会稍微公开一下,看看是否有人知道如何让run()
起作用。
答案 0 :(得分:1)
除非您在测试结束前强制执行此承诺,否则承诺无法解决。这是一种这样的方法:
$httpBackend.expectGET(......).respond(200, 'abc');
var promise = mockDataService.getWorkflowTask('http://localhost/foo');
promise.then(function (response) {
valid = "Success";
}, function (response) {
valid = "Failure";
});
//new code here
$httpBackend.flush();
expect(valid).toBe("Success");
这将强制承诺解决,您的测试应该通过。您还需要将$ httpBackend服务注入测试。
答案 1 :(得分:0)
angular.module('mock.dataService', [])
.service('mockDataService', function($http) {
this.getWorkflowTask = function(url) {
return $http.get(url)
}
})
describe('HTTP Backend Mock testing', function() {
var $httpBackend
beforeEach(angular.mock.module("mock.dataService"));
beforeEach(inject(function(_$httpBackend_) {
$httpBackend = _$httpBackend_
}))
it("Get the workflow task", angular.mock.inject(function(mockDataService) {
$httpBackend.expectGET('http://localhost/foo').respond(200);
var promise = mockDataService.getWorkflowTask('http://localhost/foo');
promise.then(function(response) {
valid = "Success";
}, function(response) {
valid = "Failure";
});
$httpBackend.flush();
expect(valid).toBe("Success");
}));
})
<link href="//safjanowski.github.io/jasmine-jsfiddle-pack/pack/jasmine.css" rel="stylesheet" />
<script src="//safjanowski.github.io/jasmine-jsfiddle-pack/pack/jasmine-2.0.3-concated.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular-mocks.js"></script>