Unit testing 测试asynchrone函数会给出意外的请求
单元测试:Unit testing 测试asynchrone函数会给出意外的请求,unit-testing,angularjs,asynchronous,jasmine,Unit Testing,Angularjs,Asynchronous,Jasmine,单元测试: "use strict"; var usersJSON = {}; describe("mainT", function () { var ctrl, scope, httpBackend, locationMock, beforeEach(module("testK")); beforeEach(inject(function ($controller, $rootScope, $httpBackend, $location, $injector) {
"use strict";
var usersJSON = {};
describe("mainT", function () {
var ctrl, scope, httpBackend, locationMock,
beforeEach(module("testK"));
beforeEach(inject(function ($controller, $rootScope, $httpBackend, $location, $injector) {
scope = $rootScope.$new();
httpBackend = $httpBackend;
locationMock = $location;
var lUrl = "../solr/users/select?indent=true&wt=json",
lRequestHandler = httpBackend.expect("GET", lUrl);
lRequestHandler.respond(200, usersJSON);
ctrl = $controller("mainT.controller.users", { $scope: scope, $location: locationMock});
httpBackend.flush();
expect(scope.users).toBeDefined();
}));
afterEach(function () {
httpBackend.verifyNoOutstandingRequest();
httpBackend.verifyNoOutstandingExpectation();
});
describe("method test", function () {
it('should test', function () {
expect(true).toBeFalsy();
});
});
});
我正在测试(工作)的控制器:
init中的异步函数给我带来了麻烦(使用../solr/users/select?indent=true&wt=json):
我认为会发生什么:
1.通知后端他将收到什么请求
2.通知后端以空JSON响应该请求
3.创建控制器(执行Search.get)
4.通知后端接收所有请求并回答它们(刷新)
但我总是会遇到以下错误:
Error: Unexpected request: GET : ../solr/users/select?indent=true&wt=json
我没有很好地处理异步搜索功能吗?如何实现这一点?在单元测试中,您的
lUrl
不应该是相对路径,也就是说,它应该是绝对路径“./solr/users/select?indent=true&wt=json”。因此,如果您的应用程序运行在”http://localhost/a/b/index.html“
,lUrl
应该是”/a/solr/…“
请注意,您还可以在
$httpBackend.expectGET()
中使用正则表达式,如果您不完全确定绝对路径以后会是什么样子,这可能会有所帮助。在beforeach中,您应该使用httpBackend.when而不是httpBackend.expect。我认为您不应该在beforeach中使用断言(expect),因此应该将其移动到单独的it()块中。我也不知道lRequestHandler是在哪里定义的。默认情况下会发送200状态,因此不需要发送。您的httpBackend系列应该如下所示:
httpBackend.when("GET", "/solr/users/select?indent=true&wt=json").respond({});
然后,您的测试应该是:
describe("method test", function () {
it('scope.user should be defined: ', function () {
expect(scope.user).toEqual({});
});
});
这不是真正的“单元”测试,更多的是行为测试
这实际上应该是一些测试:
describe('Search', function () {
var Search,
$httpBackend;
beforeEach(function () {
module('myModule');
inject(function (_Search_, _$httpBackend_) {
Search = _Search_;
$httpBackend = _$httpBackend_;
});
});
describe('get()', function () {
var mockResult;
it('should call the proper url and return a promise with the data.', function () {
mockResult = { foo: 'bar' };
$httpBackend.expectGET('http://sample.com/url/here').respond(mockResult);
var resultOut,
handler = jasmine.createSpy('result handler');
Search.get({ arg1: 'wee' }).then(handler);
$httpBackend.flush();
expect(handler).toHaveBeenCalledWith(mockResult);
$httpBackend.verifyNoOutstandingRequest();
$httpBackend.verifyNoOutstandingExpectation();
});
});
});
describe('myCtrl', function () {
var myCtrl,
$scope,
Search;
beforeEach(function () {
module('myModule');
inject(function ($rootScope, $controller, _Search_) {
$scope = $rootScope.$new();
Search = _Search;
myCtrl = $controller('MyCtrl', {
$scope: scope
});
});
});
describe('$scope.foo()', function () {
var mockResult = { foo: 'bar' };
beforeEach(function () {
//set up a spy.
spyOn(Search, 'get').andReturn({
then: function (fn) {
// this is going to execute your handler and do whatever
// you've programmed it to do.. like $scope.results = data; or
// something.
fn(mockResult);
}
});
$scope.foo();
});
it('should call Search.get().', function () {
expect(Search.get).toHaveBeenCalled();
});
it('should set $scope.results with the results returned from Search.get', function () {
expect(Search.results).toBe(mockResult);
});
});
});
实际上,您不需要将$httpBackend声明放入beforeach中,因为它只会被使用一次。相反,如果你想把声明留在那里,你可以把清理电话放在一个电话后。这两种方法都有效,但一种方法比另一种更干净。
describe('Search', function () {
var Search,
$httpBackend;
beforeEach(function () {
module('myModule');
inject(function (_Search_, _$httpBackend_) {
Search = _Search_;
$httpBackend = _$httpBackend_;
});
});
describe('get()', function () {
var mockResult;
it('should call the proper url and return a promise with the data.', function () {
mockResult = { foo: 'bar' };
$httpBackend.expectGET('http://sample.com/url/here').respond(mockResult);
var resultOut,
handler = jasmine.createSpy('result handler');
Search.get({ arg1: 'wee' }).then(handler);
$httpBackend.flush();
expect(handler).toHaveBeenCalledWith(mockResult);
$httpBackend.verifyNoOutstandingRequest();
$httpBackend.verifyNoOutstandingExpectation();
});
});
});
describe('myCtrl', function () {
var myCtrl,
$scope,
Search;
beforeEach(function () {
module('myModule');
inject(function ($rootScope, $controller, _Search_) {
$scope = $rootScope.$new();
Search = _Search;
myCtrl = $controller('MyCtrl', {
$scope: scope
});
});
});
describe('$scope.foo()', function () {
var mockResult = { foo: 'bar' };
beforeEach(function () {
//set up a spy.
spyOn(Search, 'get').andReturn({
then: function (fn) {
// this is going to execute your handler and do whatever
// you've programmed it to do.. like $scope.results = data; or
// something.
fn(mockResult);
}
});
$scope.foo();
});
it('should call Search.get().', function () {
expect(Search.get).toHaveBeenCalled();
});
it('should set $scope.results with the results returned from Search.get', function () {
expect(Search.results).toBe(mockResult);
});
});
});