间谍不与 Angular、Jasmine 和 Sinon 合作

Spying not working with Angular, Jasmine and Sinon

我试图监视控制器中定义的方法,但无论我做什么,我都会看到测试失败并显示以下消息:

Error: Expected a spy, but got Function.

我将 Karma、Jasmine 和 Sinon 与 Angular 一起使用。我很确定一切都设置正确,因为只从 $scope 中读取属性的测试通过了。

例如,我有这个非常简单的应用程序模块:

angular.module('app', []);

还有这个非常简单的控制器:

angular.module('app').controller('myController', ['$scope', function($scope) {
    $scope.test = '';
    $scope.setTest = function (newString) {
        $scope.test = newString || 'default';
    }
    $scope.updateTest = function (newString) {
        $scope.setTest(newString);
    };
}]);

我的规格文件如下:

describe('myController', function () {
    'use strict';

    beforeEach(module('app'));

    var $scope, sandbox;

    beforeEach(inject(function ($controller) {
        $scope = {};
        $controller('myController', { $scope: $scope });

        sandbox = sinon.sandbox.create();
    }));

    afterEach(function () {
        sandbox.restore();
    });

    describe('#updateTest()', function () {

        beforeEach(function () {
            sandbox.spy($scope, 'setTest');
        });

        it('updates the test property with a default value', function () {
            $scope.updateTest();

            expect($scope.test).toEqual('default');
        });

        it('calls the setTest method', function () {
            $scope.updateTest();

            expect($scope.setTest).toHaveBeenCalled();

        });

    });
});

第一个测试(它只是检查测试 属性 是否更新)通过。

我只想监视 setTest() 方法的第二个测试失败并显示上述错误消息。

如果我在 beforeEach 中注销 $scope,我可以看到 setTest 方法并且没有脚本错误。

我错过了什么?

我猜这是因为你混合了 Jasmine 和 Sinon,我认为 Sinon 间谍 sandbox.spy() 不会与 Jasmine 匹配器 expect().toHaveBeenCalled() 一起工作。您应该选择使用哪一个:

  1. 使用 Sinon 间谍并将结果转换为原语以将其传递给 Jasmine:

    sandbox.spy($scope, 'setTest');
    expect($scope.setTest.called).toBeTruthy();
    

    但是这种方法会给你更少冗长的输出:Expected true to be false,而不是通常的 Expected spy to have been called.

  2. 使用 Jasmine 间谍:

    spyOn($scope, 'setTest');
    expect($scope.setTest).toHaveBeenCalled();
    

您还可以查看工具 jasmine-sinon,它添加了额外的 Jasmine 匹配器并允许将 Sinon 间谍与 Jasmine 间谍匹配器一起使用。因此,您应该能够在示例中使用 like:

sandbox.spy($scope, 'setTest');
expect($scope.setTest).toHaveBeenCalled();