13

我有一个Angularjs应用程序,它在执行某些操作之前使用简单的 javascript 确认。

控制器:

function TokenController($scope) {
  $scope.token = 'sampleToken';

  $scope.newToken = function() {
    if (confirm("Are you sure you want to change the token?") == true) {
      $scope.token = 'modifiedToken';
    }
  };
}

看法:

<div id="tokenDiv">
  Token:{{token}} <button ng-click="newToken()">New Token</button>
</div>

现在我想进行端到端测试以检查令牌在视图中是否被正确替换。如何拦截javascript.confirm()呼叫,使其不会停止测试的执行?

测试:

it('should be able to generate new token', function () {
   var oldValues = element('#tokenDiv').text();
   element('button[ng-click="newToken()"]').click(); // Here the javascript confirm box pops up.
   expect(element('#tokenDiv').text()).not.toBe(oldValues);
});

到目前为止,我已经尝试重新定义该window.confirm函数,但实际调用抱怨它未定义。

我还想设置一个 Jasmine 间谍,window.confirm但在下面的语法中spyOn(window, 'confirm');它给了我一个错误,说你不能间谍null

我将如何进行这样的测试?

4

3 回答 3

29

另一种选择是直接创建一个间谍并自动返回true

//Jasmine 2.0
spyOn(window, 'confirm').and.callFake(function () {
     return true;
});

//Jasmine 1.3
spyOn(window, 'confirm').andCallFake(function () {
     return true;
});
于 2014-08-29T14:09:39.380 回答
13

端到端测试

请咨询该项目: https ://github.com/katranci/Angular-E2E-W​​indow-Dialog-Commands

单元测试

如果您为对话框创建服务,那么您可以在单元测试中模拟该服务,以使您的代码可测试:

控制器

function TokenController($scope, modalDialog) {
  $scope.token = 'sampleToken';

  $scope.newToken = function() {
    if (modalDialog.confirm("Are you sure you want to change the token?") == true) {
      $scope.token = 'modifiedToken';
    }
  };
}

模态对话服务

yourApp.factory('modalDialog', ['$window', function($window) {
    return {
        confirm: function(message) {
            return $window.confirm(message);
        }
    }
}]);

模态对话框模拟

function modalDialogMock() {
    this.confirmResult;

    this.confirm = function() {
        return this.confirmResult;
    }

    this.confirmTrue = function() {
        this.confirmResult = true;
    }

    this.confirmFalse = function() {
        this.confirmResult = false;
    }
}

测试

var scope;
var modalDialog;

beforeEach(module('yourApp'));

beforeEach(inject(function($rootScope, $controller) {
    scope = $rootScope.$new();
    modalDialog = new modalDialogMock();
    var ctrl = $controller('TokenController', {$scope: scope, modalDialog: modalDialog});
}));

it('should be able to generate new token', function () {
   modalDialog.confirmTrue();

   scope.newToken();
   expect(scope.token).toBe('modifiedToken');
});
于 2013-05-08T11:53:31.210 回答
7

在单元测试中,您可以像这样模拟 $window 对象:

你的测试:

beforeEach(function() {
    module('myAppName');

    inject(function($rootScope, $injector) {
        $controller = $injector.get('$controller');
        $scope = $rootScope.$new();
        var windowMock = { confirm: function(msg) { return true } }
        $controller('UsersCtrl', { $scope: $scope, $window: windowMock });
    });
});

你的控制器:

myAppName.controller('UsersCtrl', function($scope, $window) {
    $scope.delete = function() {
        var answer = $window.confirm('Delete?');
        if (answer) {
             // doing something
        }
    }
});
于 2013-09-27T11:21:47.060 回答