我不是单元测试(C#)的新手,但我对AngularJS中的单元测试非常陌生。 我正在尝试测试我的控制器,到目前为止已经能够使几个测试正常工作,但是有一些测试证明是相当困难的。
我有$ scope方法调用我们的Authentication服务,该服务返回一个promise。在“then”函数中,我正在检查用户是否确实已经过身份验证,并且基于此我将调用一个私有函数,该函数将出去并进行其他服务调用。
目前测试失败并出现以下错误:
Expected spy getConfigurationStatuses to have been called.
Error: Expected spy getConfigurationStatuses to have been called.
如果有人能帮助我指出正确的方向,我会非常感激。我将发布以下代码 - 谢谢你的帮助!
这是我的规格(无法使用的规格是“如果用户经过身份验证,则应调用特定配置”规范:
describe('EnvironmentCtrl specs', function(){
var $rootScope = null, $scope = null, ctrl = null;
var Authentication = {
getCredentials: function(){ return true; }
};
var Environment = { getConfigurationStatuses: function(){ return true; } };
beforeEach(module('ngRoute'));
beforeEach(module('environment'));
beforeEach(module(function($provide){
$provide.value('SITE_ROOT', '/');
}));
beforeEach(inject(function(_$rootScope_, _$controller_, _$timeout_, _$location_, _$q_, _Authentication_, _Environment_){
$rootScope = _$rootScope_;
$controller = _$controller_;
$timeout = _$timeout_;
$location = _$location_;
$q = _$q_;
Authentication = _Authentication_;
Environment = _Environment_;
spyOn(Authentication, 'getCredentials').andCallThrough();
spyOn(Environment, 'getConfigurationStatuses').andCallThrough();
$rootScope = _$rootScope_;
$scope = $rootScope.$new();
ctrl = $controller('EnvironmentCtrl', {$rootScope: $rootScope,$scope: $scope, $timeout: $timeout,
Eventor: {}, Controller: {}, Environment: Environment,Authentication: Authentication, ErrorService:{} });
}));
describe('When initializing the EnvironmentCtrl', function(){
// this one works fine!
it('should set default values on the scope object', function(){
expect($scope.controllerName).toEqual('EnvironmentCtrl');
expect($scope.environmentStatusType).toEqual('configurations');
expect($scope.configurationsSelected).toBe(true);
expect($scope.isDataLoaded).toBe(false);
});
// this works fine!
it('should make a call to authenticate the user', function(){
$scope.determineViewToDisplay();
expect(Authentication.getCredentials).toHaveBeenCalled();
});
// this one doesn't work!
it('should call specific configurations if user is authenticated', function(){
$scope.determineViewToDisplay();
$rootScope.isUserAuthenticated = true;
expect(Environment.getConfigurationStatuses).toHaveBeenCalled();
});
});
});
以下是单元测试中涉及的三个函数:
$scope.determineViewToDisplay = function () {
Authentication.getCredentials().then(function(){
if ($rootScope.isUserAuthenticated === true) {
$scope.isAnonymous = false;
handleAuthenticatedUserView();
} else {
Eventor.publish('event:login', false);
$scope.isAnonymous = true;
handleAnonymousUserView();
}
}, function(err){
ErrorService.handleError(err, null, $scope.controllerName);
});
};
function handleAuthenticatedUserView() {
$scope.configurationStatusTimer = $timeout(function(){
displayConfigurationStatuses(true);
}, 5);
}
function displayConfigurationStatuses(isAuthenticated) {
Environment.getConfigurationStatuses(isAuthenticated).then(function(statuses){
setConfigurationsIconStatus(statuses);
$scope.configurationStatuses = statuses;
$scope.isDataLoaded = true;
amplify.store($rootScope.productCustomerName + '-configurationStatuses', statuses, {expires: 120000});
$rootScope.showLoadingIndicator = false;
}, function(err){
ErrorService.handleError(err, null, $scope.controllerName);
});
}
答案 0 :(得分:0)
如果
看起来像DetermViewToDisplay()只调用handleAuthenticatedUserView$rootScope.isUserAuthenticated === true
但是在你打电话之前你没有将$ rootScope.isUserAuthenticated设置为true
$scope.determineViewToDisplay()
所以handleAuthenticatedUserView()永远不会被调用,反过来displayConfigurationStatuses()永远不会被调用。
答案 1 :(得分:0)
我知道这是一个较老的问题,但是......
getCredentials方法实际上是异步操作吗?这就是为什么您会看到“应该拨打电话来验证用户身份”的原因。传递,因为对该函数的调用是同步的。 getCredentials返回一个promise并继续前进。这会导致断言在解析/拒绝处理程序运行之前运行(这是最终调用被测函数的地方)。
您可以使用'完成' (或更旧的'运行/等待')Jasmine语法中的异步操作,以确保您的断言不会运行,直到所有承诺都已解决。
另外我只是注意到在超时(更多异步)内调用displayConfigurationStatuses。您可能必须模拟$ timeout服务才能立即执行,或者使handleAnonymousUserView返回一个超时执行后解析的promise。