模拟一个服务,以testing一个控制器

我有一个ParseService,我想嘲笑所有使用它的控制器,我一直在阅读有关茉莉花间谍,但它仍然不清楚。 有谁能给我一个如何模拟一个自定义服务的例子,并在Controllertesting中使用它吗?

现在我有一个控制器,使用服务来插入一本书:

BookCrossingApp.controller('AddBookCtrl', function ($scope, DataService, $location) { $scope.registerNewBook = function (book) { DataService.registerBook(book, function (isResult, result) { $scope.$apply(function () { $scope.registerResult = isResult ? "Success" : result; }); if (isResult) { //$scope.registerResult = "Success"; $location.path('/main'); } else { $scope.registerResult = "Fail!"; //$location.path('/'); } }); }; }); 

该服务是这样的:

 angular.module('DataServices', []) /** * Parse Service * Use Parse.com as a back-end for the application. */ .factory('ParseService', function () { var ParseService = { name: "Parse", registerBook: function registerBook(bookk, callback) { var book = new Book(); book.set("title", bookk.title); book.set("description", bookk.Description); book.set("registrationId", bookk.RegistrationId); var newAcl = new Parse.ACL(Parse.User.current()); newAcl.setPublicReadAccess(true); book.setACL(newAcl); book.save(null, { success: function (book) { // The object was saved successfully. callback(true, null); }, error: function (book, error) { // The save failed. // error is a Parse.Error with an error code and description. callback(false, error); } }); } }; return ParseService; }); 

我的testing到目前为止是这样的:

 describe('Controller: AddBookCtrl', function() { // // load the controller's module beforeEach(module('BookCrossingApp')); var AddBookCtrl, scope, book; // Initialize the controller and a mock scope beforeEach(inject(function($controller, $rootScope) { scope = $rootScope; book = {title: "fooTitle13"}; AddBookCtrl = $controller('AddBookCtrl', { $scope: scope }); })); it('should call Parse Service method', function () { //We need to get the injector from angular var $injector = angular.injector([ 'DataServices' ]); //We get the service from the injector that we have called var mockService = $injector.get( 'ParseService' ); mockService.registerBook = jasmine.createSpy("registerBook"); scope.registerNewBook(book); //With this call we SPY the method registerBook of our mockservice //we have to make sure that the register book have been called after the call of our Controller expect(mockService.registerBook).toHaveBeenCalled(); }); it('Dummy test', function () { expect(true).toBe(true); }); }); 

现在testing失败:

  Expected spy registerBook to have been called. Error: Expected spy registerBook to have been called. 

我做错了什么?

我做错了什么不是在beforeEach注入控制器的Mocked服务:

 describe('Controller: AddBookCtrl', function() { var scope; var ParseServiceMock; var AddBookCtrl; // load the controller's module beforeEach(module('BookCrossingApp')); // define the mock Parse service beforeEach(function() { ParseServiceMock = { registerBook: function(book) {}, getBookRegistrationId: function() {} }; }); // inject the required services and instantiate the controller beforeEach(inject(function($rootScope, $controller) { scope = $rootScope.$new(); AddBookCtrl = $controller('AddBookCtrl', { $scope: scope, DataService: ParseServiceMock }); })); it('should call registerBook Parse Service method', function () { var book = {title: "fooTitle"} spyOn(ParseServiceMock, 'registerBook').andCallThrough(); //spyOn(ParseServiceMock, 'getBookRegistrationId').andCallThrough(); scope.registerNewBook(book); expect(ParseServiceMock.registerBook).toHaveBeenCalled(); //expect(ParseServiceMock.getBookRegistrationId).toHaveBeenCalled(); }); }); 

你可以注入你的服务,然后像这样使用spyOn.and.returnValue():

 beforeEach(angular.mock.module('yourModule')); beforeEach(angular.mock.inject(function($rootScope, $controller, ParseService) { mock = { $scope: $rootScope.$new(), ParseService: ParseService }; $controller('AddBookCtrl', mock); })); it('should call Parse Service method', function () { spyOn(mock.ParseService, "registerBook").and.returnValue({id: 3}); mock.$scope.registerNewBook(); expect(mock.ParseService.registerBook).toHaveBeenCalled(); }); 

继贾维托4年后的回答 。 茉莉花2.0改变了他们的语法,通过间谍真正的方法。

更改:

 spyOn(ParseServiceMock, 'registerBook').andCallThrough(); 

至:

 spyOn(ParseServiceMock, 'registerBook').and.callThrough(); 

资源

在您的项目中包含angular-mocks.js ,并通过以下链接仔细阅读。