【发布时间】:2016-09-17 07:11:26
【问题描述】:
我在测试服务返回的承诺中设置的控制器值时遇到了麻烦。我正在使用 Sinon 来存根服务(Karma 运行测试,Mocha 作为框架,Chai 用于断言)。
我对快速解决问题的兴趣不如对问题的理解。我已经阅读了很多,我在代码和测试下面有一些笔记。
这是代码。
.controller('NavCtrl', function (NavService) {
var vm = this;
NavService.getNav()
.then(function(response){
vm.nav = response.data;
});
})
.service('NavService', ['$http', function ($http) {
this.getNav = function () {
return $http.get('_routes');
};
}]);
这是测试:
describe('NavCtrl', function () {
var scope;
var controller;
var NavService;
var $q;
beforeEach(module('nav'));
beforeEach(inject(function($rootScope, $controller, _$q_, _NavService_){
NavService = _NavService_;
scope = $rootScope.$new();
controller = $controller;
}));
it('should have some data', function () {
var stub = sinon.stub(NavService, 'getNav').returns($q.when({
response: {
data: 'data'
}
}));
var vm = controller("NavCtrl", {
$scope: scope,
NavService: NavService
});
scope.$apply();
stub.callCount.should.equal(1);
vm.should.be.defined;
vm.nav.should.be.defined;
});
});
正在调用存根,即测试通过,并且定义了vm,但vm.nav 永远不会获取数据并且测试失败。我认为,我如何处理存根的承诺是罪魁祸首。一些注意事项:
基于reading elsewhere,我调用
scope.$apply来设置值,但由于没有将作用域注入到原始控制器中,我不肯定这会成功。这个article 指向angular docs on $q。另一篇文章推荐 using $timeout 作为“真正完成承诺”的内容。这篇文章还建议使用“sinon-as-promised”,这是我在上面没有做的。我试过了,但没有发现区别。
此 Stack Overflow 答案使用 scope.$root.$digest(),因为“如果您的范围对象的值来自承诺结果,您将需要调用 scope.$root.$digest()”。但同样,同样的测试失败。同样,这可能是因为我没有使用范围。
关于stubing promise,我也试过sinon sandbox way,但结果是一样的。
我尝试使用
$scope重写测试,以确保vmstyle 没有问题,但测试仍然失败。
最后,我可能是错的:存根和承诺可能不是问题,这是我错过的不同和/或明显的东西。
非常感谢任何帮助,如果我能澄清以上任何内容,请告诉我。
【问题讨论】:
-
你说作用域没有注入到原始控制器上,但是你在实例化控制器时传递了它。如果您的控制器不使用注入的 $scope 在测试期间传递它不会让它使用它。大多数时候我使用
$rootScope.apply()来触发承诺解决。使用根范围消除了未触发承诺的可能性 -
angular 的 $q 服务在内部使用 $rootScope,他们建议使用 $rootScope apply - docs.angularjs.org/api/ng/service/$q#testing
标签: angularjs unit-testing promise mocha.js sinon