[英]Angularjs unit testing resolving promises
I'm probably doing this wrong but I can't figure out how to fix it. 我可能做错了,但我不知道如何解决。
I want to test a controller that uses a resource (ngResource) and I want to use a Spy as a test double for the resource so it doesn't actually do the http call. 我想测试使用资源(ngResource)的控制器,并且想将Spy用作资源的测试双倍,因此它实际上不会执行http调用。 In the code below I just want to test the search function in the controller. 在下面的代码中,我只想测试控制器中的搜索功能。
Controller: 控制器:
controllers = angular.module('app.controllers');
controllers.controller('landingCtrl', ['$scope', '$q', 'categoryResource', function ($scope, $q, categoryResource) {
$scope.search = function (text) {
console.log('searching for: ' + text);
var deferred = $q.defer();
categoryResource.query({ searchTerm: text }, function (result) {
if (result.length == 0) {
deferred.resolve(['No results found']);
} else {
deferred.resolve(result);
}
});
return deferred.promise;
}
}]);
Service: 服务:
var services = angular.module('app.services');
services.factory('categoryResource', ['$resource', function ($resource) {
var resource = $resource('/api/category');
return resource;
}]);
Spec for landingCtrl: 登陆规范:
describe('Controller: landingCtrl ', function () {
var $q,
$rootScope,
$scope;
beforeEach(module('ngResource'));
beforeEach(module('app.services'));
beforeEach(module('app.controllers'));
beforeEach(inject(function (_$rootScope_, _$q_) {
$q = _$q_;
$rootScope = _$rootScope_;
}));
// mock any depencencies, like scope. $resource or $http
beforeEach(inject(function ($controller, $injector, categoryResource) {
$scope = $rootScope.$new();
spyOn(categoryResource, 'query').andCallFake(function (searchText) {
console.log('query fake being called');
var deferred = $q.defer();
deferred.resolve(['Test', 'Testing', 'Protester']);
return deferred.promise;
});
landingCtrl = $controller('landingCtrl', {
'$scope': $scope,
'$q': $q,
'categoryResource': categoryResource
});
}));
afterEach(inject(function ($rootScope) {
$rootScope.$apply();
}));
it('should return words with "test" in them"', function () {
$scope.search('test').then(function (results) {
console.log(results);
expect(results).toContain('Test');
});
$scope.$apply();
});
});
The test executes without errors but it passes without ever resolving the promise so my code inside the "then" function never gets called. 测试执行没有错误,但是通过却没有解决承诺,因此“ then”函数中的代码从未被调用。 What am I doing wrong? 我究竟做错了什么?
I've created a plunker with the above and a test that should fail: 我用上面的代码创建了一个punker,并且测试应该失败了:
http://plnkr.co/edit/adE6fTajgbDoM33rtbZS?p=preview http://plnkr.co/edit/adE6fTajgbDoM33rtbZS?p=preview
Your spec is mocking categoryResource.query()
so it returns a promise, but your controller isn't expecting that. 您的规范是在模拟categoryResource.query()
因此它返回一个诺言,但您的控制器并不期望这样。 It calls query()
and passes a callback, and within that callback it does its thing. 它调用query()
并传递一个回调,然后在该回调中执行其操作。 In other words, your spec isn't testing what your controller does. 换句话说,您的规范并未测试控制器的功能。
Here's your fixed spec: 这是您的固定规格:
spyOn(categoryResource, 'query').andCallFake(function (searchText, callback) {
console.log('query fake being called');
callback(['Test', 'Testing', 'Protester']);
});
...
it('should return words with "test" in them"', function () {
var results;
$scope.search('test').then(function (_results_) {
console.log(results);
results = _results_;
});
$scope.$apply();
expect(results).toContain('Test');
});
Notice that I have moved the expectation outside the then()
callback, so your test breaks if the promise isn't resolved. 请注意,我已经将期望值移到了then()
回调之外,因此如果未解决承诺,您的测试就会失败。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.