よく読んだ後、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
をモックできるようにしたいと思います。これは可能ですか?
これまでの私の試みは何も生み出していません。これは私の試みです:
//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: 'undefined'はオブジェクトではありません( '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の動作に関するテストをいくつか追加しましたが、これを試してみるまではわかりませんでした。
ゴグ