7

我的 Angular 控制器中有一个函数,如下所示:

$scope.myFunction = function(){
    $scope.myVariable = "something";
    $scope.myOtherVariable = "something else";
    window.location.href = "/path/to/page"; 
}

一个简单的 Jasmine 测试涵盖了上述功能,如下所示:

describe('my test', function(){
    it('should pass', function(){
        scope.myFunction();
        expect(scope.myVariable).toBe('something');
        expect(scope.myOtherVariable).toBe('something else');     
    });
});

上述测试本身通过,但随后 Karma 在控制台中抛出以下错误:

你的一些测试做了一个完整的页面重新加载!

页面重定向导致 Karma 发出此警告。解决这个问题的最佳方法是什么?

我考虑在 Jasmine 测试中同时给出匿名函数和 Angular 名称,然后在原始函数中使用arguments.callee.caller.name来确定该函数是由自身调用还是被 Jasmine 调用。不幸的是,arguments.callee.caller.name总是返回 undefined,我怀疑这是由 Angular 和 Jasmine 相互链接的方式引起的。

4

2 回答 2

22

很久没有问这个问题了,但是下面的方法应该更干净:

通过将原始函数更改为使用 Angular 的 $window 服务而不是浏览器窗口对象,可以编写不需要修改生产代码或考虑任何运行时参数的测试。这当然要求 $window 是找到该函数的控制器的依赖项。

使用angular-mocks/ngMock,例如:

var fakeWindow = {
  location: {
    href: ''
  }
}
// instantiate controller with mock window
beforeEach(inject(function($controller) {
  $controller('YourCtrlName', {
    $window: fakeWindow
  });
}));

应该允许测试通过,假设控制器不需要 $window 其他任何东西。

于 2014-12-01T22:08:03.670 回答
4

您可以创建一个执行导航的函数,例如

$scope.Navigate = function() {
    window.location.href = "/path/to/page";
};

甚至在某些服务中更好

app.factory('navigator', function() {
    return {
        Navigate: function(path) {
            window.location.href = path;
        }
    };
});

然后在您的测试中,您可以在 Navigate 上使用间谍,以确保调用了导航,但实际上并没有调用导航。

于 2014-03-13T20:57:48.157 回答