javascript 测试我的 AngularJS 控制器时,如何在 $http.get 承诺中模拟结果?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17825798/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I mock the result in a $http.get promise when testing my AngularJS controller?
提问by Mendhak
After much reading, it seems that the recommended way to call a web service from an AngularJS controller is to use a factory and return a promise from that.
经过大量阅读,从 AngularJS 控制器调用 Web 服务的推荐方法似乎是使用工厂并从中返回承诺。
Here I have a simple factory which calls a sample API.
在这里,我有一个调用示例 API 的简单工厂。
myApp.factory('MyFactory', ['$http',function($http) {
var people = {
requestPeople: function(x) {
var url = 'js/test.json';
return $http.get(url);
}
};
return people;
}]);
And this is how I call it in the controller
这就是我在控制器中调用它的方式
myApp.controller('MyCtrl1', ['$scope', 'MyFactory', function ($scope, MyFactory) {
MyFactory.requestPeople(22).then(function(result) {
$scope.peopleList = result;
});
}]);
While it works fine, I would like to be able to mock the resultthat is passed in when thenis called. Is this possible?
虽然它工作正常,但我希望能够模拟调用result时传入的then。这可能吗?
My attempt so far has produced nothing. This is my attempt:
到目前为止,我的尝试没有产生任何结果。这是我的尝试:
//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');
}));
The error that I get when running this in karma runner, is
我在 karma runner 中运行时得到的错误是
TypeError: 'undefined' is not an object (evaluating 'scope.peopleList.one')
类型错误:'undefined' 不是一个对象(评估 'scope.peopleList.one')
How can I get this test working with my mocked data?
我怎样才能让这个测试与我的模拟数据一起工作?
回答by GogLlundain
I don't think $httpBackend is what you're after here, you want the whole factory to be mocked without it having a dependency on $http?
我不认为 $httpBackend 是您在这里所追求的,您希望整个工厂在不依赖于 $http 的情况下被模拟?
Take a look at $q, in particular the code sample under the Testing header. Your issue might be resolved with code that looks like this:
看看$q,特别是测试标题下的代码示例。您的问题可能会通过如下所示的代码解决:
'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" });
});
});
I've added some tests around what $apply does, I didn't know that until I started playing with this!
我已经添加了一些关于 $apply 功能的测试,直到我开始玩这个我才知道!
Gog
高格

