如何使用Jasmine、AngularJs测试uu.defer()
我已经问过这个问题,重点是范围在终端中不存在,但它存在于Chrome调试工具中。尽管有答案,它还是没有得到修复 问题是测试bellow指令的正确语法是什么,尤其是行如何使用Jasmine、AngularJs测试uu.defer(),angularjs,unit-testing,jasmine,underscore.js,Angularjs,Unit Testing,Jasmine,Underscore.js,我已经问过这个问题,重点是范围在终端中不存在,但它存在于Chrome调试工具中。尽管有答案,它还是没有得到修复 问题是测试bellow指令的正确语法是什么,尤其是行expect(scope.measurementScroll).toBe(true)。在浏览网页时,我找不到任何类似的问题,大多数问题都与$q.defer()有关,在我的例子中,这里有下划线方法\uu.defer() 控制器 'use strict'; angular.module('myApp') .controller('Me
expect(scope.measurementScroll).toBe(true)代码>。在浏览网页时,我找不到任何类似的问题,大多数问题都与$q.defer()
有关,在我的例子中,这里有下划线方法\uu.defer()
控制器
'use strict';
angular.module('myApp')
.controller('MeasurementsTimelineCtrl', ['$scope', '$state', 'Measurements', function($scope, $state, Measurements) {
$scope.measurements = null;
var userId = $scope.currentUser ? $scope.currentUser.id : null;
if (userId) {
var listOfMeasurements = Measurements.userIndex(userId);
listOfMeasurements.then(function(data){
$scope.measurements = data;
$scope.$broadcast('measurements-updated', $scope.measurements);
});
}
}]);
指令:
'use strict';
angular.module('myApp')
.directive('dashboardMeasurementTimeline', ['$window', function($window) {
return {
restrict: 'E',
templateUrl: 'myView.html',
controller: 'MeasurementsTimelineCtrl',
link: function(scope, element){
scope.$on('measurements-updated', function(measurements) {
_.defer(function(){
if(measurements) {
scope.measurementScroll = true;
}
});
});
}
};
}]);
试验
“严格使用”;
描述('指令:仪表板度量TTIMELINE',函数(){
var$rootScope,$compile,element,scope;
beforeach(函数(){
模块(“myApp”);
注入(函数($injector){
$rootScope=$injector.get(“$rootScope”);
$compile=$injector.get(“$compile”);
});
scope=$rootScope.$new();
元素=角度。元素(“”);
元素=$compile(元素)(范围);
scope.currentUser={id:'someId'};
范围。$digest();
scope.measurements=[{id:'someId',测试时间:'Tue,2014年12月30日14:00:00-0000'},
{id:'someId',测试时间:'Thu,2014年11月20日03:00:00-0000'},];
范围:$broadcast('measurements-updated',scope.measurements);
作用域:$apply();
});
它('应该为measurementScroll'分配真值',函数(){
expect(scope.measurementScroll).toBe(true);
});
});
您可以通过注入模拟下划线库来实现这一点,该库带有测试中定义的defer
函数。实现这一点的一种方法是定义自己的工厂,\uu
,然后可以很容易地对其进行模拟:
app.factory('_', function($window) {
return $window._;
});
然后在指令中,您必须通过注入来使用它:
app.directive('dashboardMeasurementTimeline', ['_', function(_) {
在测试中,您可以模拟它:
var deferCallback;
beforeEach(module(function($provide) {
deferCallback = null;
$provide.value('_', {
defer: function(callback) {
deferCallback = callback;
}
});
}));
这意味着指令将使用mock\uuu
,而不是真实的,它将传递给defer
的回调保存为deferCallback
,以便您可以在需要时调用它:
scope.$broadcast('measurements-updated', scope.measurements);
deferCallback();
这使得测试同步,这通常比使用done()
您可以在@Michal Charezma上看到上面的内容,它为这个问题提供了一个很好的解决方案,实际上它是一个解决方案,但事实证明它对其余的
函数有一些其他限制。
例如:
angular.element(scrollContainer).bind('scroll', _.throttle(scope.disableButtons, 500));
引发一个错误,油门未定义
按照@Michal的逻辑,我们找到了另一个解决方案,可以让..throttle()
这样的函数正常工作。因此,与其导入\uuuu
并使用:
app.factory('_', function($window) {
return $window._;
});
可以仅从规范中模拟defer
函数,如:
var deferCallback = $window._.defer.mostRecentCall.args[0];
deferCallback()
如果您没有lodash作为要注入的服务,您只需监视defer
方法,如果您关心传递的函数的执行,那么您只需设置callFake
并调用传递给realdefer
的参数函数:
spyOn(_, 'defer').and.callFake(f => f());
更深入地说,假设您有以下电话:
function toTest() {
_.defer(() => service.callAFunction());
}
然后在测试中,你可以说:
it('should call service.callAFunction', () => {
spyOn(service, 'callAFunction');
spyOn(_, 'defer').and.callFake(f => f());
toTest();
expect(_.defer).toHaveBeenCalled();
expect(service.callAFunction).toHaveBeenCalled();
}
我使用的插件是karma jasmine:0.1.5
,而谷歌发现它相当于jasmine 2.0非常感谢亲爱的@Michal Charezma,你的解决方案很棒,解决了这个问题。我现在有一个小问题,那就是在模拟\uu
并将其导入指令之后,当使用.
的其他方法时,它会引发一个错误,例如我正在使用:angular.element(scrollContainer.bind('scroll',u.throttle(scope.disableButtons,500))
方法throttle()
似乎没有exist@Max您应该能够将throttle
添加到传递给$provide.value
的对象中。我认为此方法实际上不会生成模拟对象。我怀疑这甚至可能导致回调延迟执行两次,一次是强制执行的,另一次是在延迟调用初始化超时后执行的。哦,这真的很有趣,我必须再次检查规范。多谢各位。)
it('should call service.callAFunction', () => {
spyOn(service, 'callAFunction');
spyOn(_, 'defer').and.callFake(f => f());
toTest();
expect(_.defer).toHaveBeenCalled();
expect(service.callAFunction).toHaveBeenCalled();
}