如何测试从 promise 对象获取数据的控制器
How test controller who gets data from promise object
我有控制器从 promise 对象获取数据。
控制器看起来像这样:
MyApp.controller("BookListController", ["$scope", "BookListModel","LibraryService", function($scope, BookListModel, LibraryService) {
LibraryService.getLibraryData().then(function(result) {
$scope.books = BookListModel.createBookList(result.bookList.data, result.authorList.data, result.publisherList.data);
});
}]);
这是我的工厂,它从 REST 服务获取数据。
MyApp.factory("LibraryService", function($http, $q) {
var service = {};
var libraryDataPromise = $q.defer();
$q.all({
books : $http.get("http://localhost:8080/library/service/books"),
authors : $http.get("http://localhost:8080/library/service/authors"),
publishers : $http.get("http://localhost:8080/library/service/publishers")
}).then(function(response) {
libraryDataPromise.resolve({
bookList : response.books,
authorList : response.authors,
publisherList : response.publishers
});
});
service.getLibraryData = function() {
return libraryDataPromise.promise;
}
return service;
});
好的,就这些。现在是时候展示我的测试是谁写的了。
describe("Book_App Controllers", function() {
describe("BookListController Test", function() {
var BookListModelMock, LibraryServiceMock, scope = {}, controller
,deferred, promise;
beforeEach(function() {
module("MyApp");
BookListModelMock = new function() {
this.createBookList = function(a, b, c) {
return [{},{},{}];
};
};
});
beforeEach(inject(function($rootScope, $controller ) {
scope = $rootScope.$new();
controller = $controller("BookListController",
{$scope : scope, BookListModel : BookListModelMock});
}));
beforeEach(inject(function($q) {
deferred = $q.defer();
promise = deferred.promise;
deferred.resolve([
{ data : [{}, {}, {}]}
])
LibraryServiceMock = function() {
var service = {};
service.getLibraryData = function() {
return promise;
}
};
}));
it("should contains three books", inject(function($rootScope) {
$rootScope.$apply();
expect(scope.books.length).toBe(3);
}));
});
});
当我 运行 测试时,Jasmine 抛出:错误:意外请求:GET http://localhost:8080/library/service/books
预计不会有更多请求
我知道这个问题是什么意思,但我不知道如何解决它。我应该模拟 $http 吗?我阅读了如何测试 promise 和 defer 但教程描述了如何测试包含 $q 操作的函数,而不是描述如何测试依赖于包含 $q 操作的函数的函数。
您的 LibraryServiceMock 未被使用。
您需要在创建控制器之前创建模拟,然后按照向新控制器提供 BookListModelMock 的相同方式使用它。
当您编写 LibraryService 测试时,您可以使用 $httpBackend.expect() 来模拟请求:https://docs.angularjs.org/api/ngMock/service/$httpBackend
我有控制器从 promise 对象获取数据。
控制器看起来像这样:
MyApp.controller("BookListController", ["$scope", "BookListModel","LibraryService", function($scope, BookListModel, LibraryService) {
LibraryService.getLibraryData().then(function(result) {
$scope.books = BookListModel.createBookList(result.bookList.data, result.authorList.data, result.publisherList.data);
});
}]);
这是我的工厂,它从 REST 服务获取数据。
MyApp.factory("LibraryService", function($http, $q) {
var service = {};
var libraryDataPromise = $q.defer();
$q.all({
books : $http.get("http://localhost:8080/library/service/books"),
authors : $http.get("http://localhost:8080/library/service/authors"),
publishers : $http.get("http://localhost:8080/library/service/publishers")
}).then(function(response) {
libraryDataPromise.resolve({
bookList : response.books,
authorList : response.authors,
publisherList : response.publishers
});
});
service.getLibraryData = function() {
return libraryDataPromise.promise;
}
return service;
});
好的,就这些。现在是时候展示我的测试是谁写的了。
describe("Book_App Controllers", function() {
describe("BookListController Test", function() {
var BookListModelMock, LibraryServiceMock, scope = {}, controller
,deferred, promise;
beforeEach(function() {
module("MyApp");
BookListModelMock = new function() {
this.createBookList = function(a, b, c) {
return [{},{},{}];
};
};
});
beforeEach(inject(function($rootScope, $controller ) {
scope = $rootScope.$new();
controller = $controller("BookListController",
{$scope : scope, BookListModel : BookListModelMock});
}));
beforeEach(inject(function($q) {
deferred = $q.defer();
promise = deferred.promise;
deferred.resolve([
{ data : [{}, {}, {}]}
])
LibraryServiceMock = function() {
var service = {};
service.getLibraryData = function() {
return promise;
}
};
}));
it("should contains three books", inject(function($rootScope) {
$rootScope.$apply();
expect(scope.books.length).toBe(3);
}));
});
});
当我 运行 测试时,Jasmine 抛出:错误:意外请求:GET http://localhost:8080/library/service/books 预计不会有更多请求
我知道这个问题是什么意思,但我不知道如何解决它。我应该模拟 $http 吗?我阅读了如何测试 promise 和 defer 但教程描述了如何测试包含 $q 操作的函数,而不是描述如何测试依赖于包含 $q 操作的函数的函数。
您的 LibraryServiceMock 未被使用。 您需要在创建控制器之前创建模拟,然后按照向新控制器提供 BookListModelMock 的相同方式使用它。
当您编写 LibraryService 测试时,您可以使用 $httpBackend.expect() 来模拟请求:https://docs.angularjs.org/api/ngMock/service/$httpBackend