如何在Karma / jasmine中模拟window.location函数

时间:2015-06-17 15:26:51

标签: angularjs unit-testing karma-jasmine

我想在Karma中模拟一个在点击下载按钮后返回文件的功能。 我有以下AngularJS控制器:

var secure = angular.module('secure', []);
secure.controller('ProcedureController', ProcedureController);
ProcedureController.$inject = ['$controller', '$rootScope', '$scope', '$http'];

function ProcedureController($controller, $rootScope, $scope, $http) {

  ... // Controller does more stuff

  var href = window.location.href.split('/');
  var baseUrl = href[0] + '//' + href[2];
  var url = baseUrl + "/secure/regulations";

  $http.get(url)
    .success(function (data) {
        $scope.questions = data[0];
    })

  $scope.download = function (msg) {
    window.location = url + "/" + msg + "/attachment";
  }
}

window.location对象只调用一个RESTful服务,直接为他提供所需的文件。 这基本上就是我的尝试测试:

describe('ProcedureController', function () {
  beforeEach(module('secure'));

  beforeEach(inject(function ($rootScope, $http, $controller, $injector) {
    scope = $rootScope.$new();
    ProcedureController = $controller('ProcedureController', {
        $scope: scope,
        $http: $http
    });
  }));

  it ('should download something', function() {
    expect(scope.download(1)).toBeDefined();
  });

 });

所以,我的想法是检查何时调用 scope.download 函数,如果它返回正确的url,即当我尝试 scope.download(1)时,预期答案大致为 / secure / regulations / 1 / attachment

我该如何嘲笑它?任何帮助表示赞赏!

2 个答案:

答案 0 :(得分:13)

改为使用$window

var secure = angular.module('secure', []);
secure.controller('ProcedureController', ProcedureController);
ProcedureController.$inject = ['$controller', '$rootScope', '$scope', '$http', '$window'];

function ProcedureController($controller, $rootScope, $scope, $http, $window) {

  ... // Controller does more stuff

  var href = $window.location.href.split('/');
  var baseUrl = href[0] + '//' + href[2];
  var url = baseUrl + "/secure/regulations";

  $http.get(url)
    .success(function (data) {
        $scope.questions = data[0];
    })

  $scope.download = function (msg) {
    $window.location = url + "/" + msg + "/attachment";
  }
}

describe('ProcedureController', function () {
  var windowObj = {location: {href: ''}};

  beforeEach(mock.module(function($provide) {
     $provide.value('$window', windowObj);
  }));
  beforeEach(module('secure'));

  beforeEach(inject(function ($rootScope, $http, $controller, $injector) {
    scope = $rootScope.$new();
    ProcedureController = $controller('ProcedureController', {
        $scope: scope,
        $http: $http
    });
  }));

  it ('should download something', function() {
    expect(scope.download).toBeDefined();
    scope.download(1);
    expect(windowObj.location.href).toEqual('/secure/regulations/1/attachment');
  });

 });

答案 1 :(得分:0)

我想这里有很多变数,但让我们从测试开始。首先,你真的不需要"嘲笑它"因为您正在通过正在加载某种形式的浏览器的Karma运行Jasmine测试。我希望您正在使用PhantomJS而非Chrome之类的内容。

但是,让我们从PhantomJS开始。您的测试代码应该如下所示:

it ('should download something', function() {
  scope.download(1);
  expect(window.location).toBeDefined();
  expect(window.location).toBe('some static URL that it should be');
});

但是,您需要修复控制器的初始化。你需要确保你能满足这条线的需要:

var href = window.location.href.split('/');

这意味着在这里构建控制器时:

ProcedureController = $controller('ProcedureController', {

您需要在执行window.location 之前将$controller设置为,以便正确构建url变量。

现在,如果您正在使用Chrome,那么您可能会在浏览器中看到真正的动态。我不认为这会导致任何问题,但这不是必要的。最好使用PhantomJS,以便您可以在控制台中运行这些测试。