Angularjs: 使用 spyOn 模拟 location.path() 进行单元测试
Angularjs: mock location.path() with spyOn for a unit test
我已经阅读了这篇文章 post(以及其他文章),但我无法让这个简单的单元测试发挥作用。我正在使用 Jasmine 的版本 2。
我的工厂很简单:
angular.module('myApp')
.factory('detectPath', function ($location, $rootScope) {
'use strict';
var locationPath = $location.path()
function getPath () {
if (locationPath === '/') {
locationPath = 'home';
} else {
locationPath = '';
}
$rootScope.path = locationPath;
}
getPath();
return locationPath;
});
我的单元测试也很简单:
'use strict';
describe('Factory: detectPath', function () {
var detectPath, $rootScope, $location;
beforeEach(module('myApp'));
beforeEach(inject(function (_detectPath_, _$rootScope_, _$location_) {
detectPath = _detectPath_;
$rootScope = _$rootScope_;
$location = _$location_;
spyOn($location, 'path').and.returnValue('/');
}));
it('should return pathName', function ($location) {
expect($rootScope.path).toBe('home');
});
});
这没有通过测试(我收到错误 expect false 为 "home")。
我做错了什么?
有没有办法验证是否已调用 spyOn(仅一次)?
您的代码有两个主要问题。
首先,您的 getPath()
函数在您设置间谍之前执行。您应该在之前的 beforeEach
中设置间谍或在测试中注入您的工厂(我选择了第二种解决方案)。
第二个问题(尚未影响测试)是您使用测试函数参数隐藏了 $location
变量 - 您将无法访问它,因为它始终未定义。删除此 arg 后,我可以测试是否使用 expect(...).toHaveBeenCalled()
.
调用了 spy
这是一个工作代码:
describe('Factory: detectPath', function () {
var detectPath, $rootScope, $location;
beforeEach(module('myApp'));
beforeEach(inject(function (_$rootScope_, _$location_) {
$rootScope = _$rootScope_;
$location = _$location_;
spyOn($location, 'path').and.returnValue('/');
}));
it('should return pathName', function () {
inject(function (detectPath) {
expect($location.path).toHaveBeenCalled();
expect($rootScope.path).toBe('home');
});
});
});
和JSFiddle(使用 Jasmine 1.3,但此示例中的唯一区别是您在 Jasmine 2 中调用 and.returnValue
,在 Jasmine 1.3 中调用 returnValue
)。
我已经阅读了这篇文章 post(以及其他文章),但我无法让这个简单的单元测试发挥作用。我正在使用 Jasmine 的版本 2。 我的工厂很简单:
angular.module('myApp')
.factory('detectPath', function ($location, $rootScope) {
'use strict';
var locationPath = $location.path()
function getPath () {
if (locationPath === '/') {
locationPath = 'home';
} else {
locationPath = '';
}
$rootScope.path = locationPath;
}
getPath();
return locationPath;
});
我的单元测试也很简单:
'use strict';
describe('Factory: detectPath', function () {
var detectPath, $rootScope, $location;
beforeEach(module('myApp'));
beforeEach(inject(function (_detectPath_, _$rootScope_, _$location_) {
detectPath = _detectPath_;
$rootScope = _$rootScope_;
$location = _$location_;
spyOn($location, 'path').and.returnValue('/');
}));
it('should return pathName', function ($location) {
expect($rootScope.path).toBe('home');
});
});
这没有通过测试(我收到错误 expect false 为 "home")。
我做错了什么? 有没有办法验证是否已调用 spyOn(仅一次)?
您的代码有两个主要问题。
首先,您的 getPath()
函数在您设置间谍之前执行。您应该在之前的 beforeEach
中设置间谍或在测试中注入您的工厂(我选择了第二种解决方案)。
第二个问题(尚未影响测试)是您使用测试函数参数隐藏了 $location
变量 - 您将无法访问它,因为它始终未定义。删除此 arg 后,我可以测试是否使用 expect(...).toHaveBeenCalled()
.
这是一个工作代码:
describe('Factory: detectPath', function () {
var detectPath, $rootScope, $location;
beforeEach(module('myApp'));
beforeEach(inject(function (_$rootScope_, _$location_) {
$rootScope = _$rootScope_;
$location = _$location_;
spyOn($location, 'path').and.returnValue('/');
}));
it('should return pathName', function () {
inject(function (detectPath) {
expect($location.path).toHaveBeenCalled();
expect($rootScope.path).toBe('home');
});
});
});
和JSFiddle(使用 Jasmine 1.3,但此示例中的唯一区别是您在 Jasmine 2 中调用 and.returnValue
,在 Jasmine 1.3 中调用 returnValue
)。