经过大量阅读后,看来从AngularJS控制器调用Web服务的推荐方法是使用工厂并从中返回承诺。
在这里,我有一个简单的工厂,可以调用示例API。
myApp.factory('MyFactory', ['$http',function($http) { var people = { requestPeople: function(x) { var url = 'js/test.json'; return $http.get(url); } }; return people; }]);
这就是我在控制器中称呼它的方式
myApp.controller('MyCtrl1', ['$scope', 'MyFactory', function ($scope, MyFactory) { MyFactory.requestPeople(22).then(function(result) { $scope.peopleList = result; }); }]);
虽然效果很好,但我希望能够模拟在调用result时传递的then。这可能吗?
result
then
到目前为止,我的尝试没有产生任何效果。这是我的尝试:
//Fake service var mockService = { requestPeople: function () { return { then: function () { return {"one":"three"}; } } } }; //Some setup beforeEach(module('myApp.controllers')); var ctrl, scope; beforeEach(inject(function ($rootScope, $controller) { scope = $rootScope.$new(); ctrl = $controller('MyCtrl1', { $scope: scope, MyFactory: mockService }); })); //Test it('Event Types Empty should default to false', inject(function () { expect(scope.peopleList.one).toBe('three'); }));
我在业力赛跑者中运行此错误是
TypeError:“未定义”不是对象(评估“ scope.peopleList.one”)
如何使此测试与模拟数据一起使用?
我不认为$ httpBackend是您追求的目标,您希望在不依赖$ http的情况下模拟整个工厂吗?
看一下$ q,特别是Testing标头下的代码示例。您的问题可以通过以下代码解决:
'use strict'; describe('mocking the factory response', function () { beforeEach(module('myApp.controllers')); var scope, fakeFactory, controller, q, deferred; //Prepare the fake factory beforeEach(function () { fakeFactory = { requestPeople: function () { deferred = q.defer(); // Place the fake return object here deferred.resolve({ "one": "three" }); return deferred.promise; } }; spyOn(fakeFactory, 'requestPeople').andCallThrough(); }); //Inject fake factory into controller beforeEach(inject(function ($rootScope, $controller, $q) { scope = $rootScope.$new(); q = $q; controller = $controller('MyCtrl1', { $scope: scope, MyFactory: fakeFactory }); })); it('The peopleList object is not defined yet', function () { // Before $apply is called the promise hasn't resolved expect(scope.peopleList).not.toBeDefined(); }); it('Applying the scope causes it to be defined', function () { // This propagates the changes to the models // This happens itself when you're on a web page, but not in a unit test framework scope.$apply(); expect(scope.peopleList).toBeDefined(); }); it('Ensure that the method was invoked', function () { scope.$apply(); expect(fakeFactory.requestPeople).toHaveBeenCalled(); }); it('Check the value returned', function () { scope.$apply(); expect(scope.peopleList).toBe({ "one": "three" }); }); });
我已经围绕$ apply的功能添加了一些测试,直到我开始玩这个游戏时我才知道!
高格