1

$scope.$watch のリスナー関数をスパイしようとすると、決してスパイオンを呼び出さないようなものです

http://jsfiddle.net/b8LoLwLb/1/

私のコントローラー

angular.module('angularApp')
    .controller('MainCtrl', function ($scope) {
        $scope.name = '';

        this.changeName = function () {
            console.log('the name has change to ' + $scope.name);
        };

        $scope.$watch('name', this.changeName);
    });

私のテスト

describe('Controller: MainCtrl', function () {

    // load the controller's module
    beforeEach(module('angularApp'));

    var MainCtrl,
        scope;

    // Initialize the controller and a mock scope
    beforeEach(inject(function ($controller, $rootScope) {
        scope = $rootScope.$new();
        MainCtrl = $controller('MainCtrl', {
            $scope: scope
        });
    }));

    it('should check if watcher was triggered', function () {
        // Spy the listener funtion
        spyOn(MainCtrl, 'changeName');

        // Change the watched property
        scope.name = 'facu';

        // Digest to trigger the watcher.
        scope.$digest();

        // Expect the function to have been called
        expect(MainCtrl.changeName).toHaveBeenCalled();
    });
});

問題は、関数をスパイする代わりに、テストが関数を実行してコンソール ログを出力することです。

angular 1.4を使用しています

4

1 に答える 1

1

これは予想される動作であり、jasmine や angular とは関係ありませんが、プロパティが保持する関数参照と関係があります。コントローラのインスタンス化を行うと、 (その時点で$scope.$watch('name', this.changeName))が保持する関数参照が監視されるように設定されます。コントローラーインスタンスの関数をスパイしても(後で)、コントローラーインスタンスのプロパティによって保持される関数参照は変更されるだけで(呼び出しを追跡するためにジャスミンによって作成されたラッパー関数に)変更されますが、ウォッチャーは変更されません。オリジナル関数リファレンス。したがって、watch が実行されると、後でプロパティに設定した spy func 参照ではなく、実際の関数参照が実行されます。this.changeNamechangeNamechangeName

代わりに、コントローラーでこれを行う場合:

   var vm = this;
   $scope.$watch('name', function(){
       vm.changeName();
   });

テストに合格することがわかります。

于 2015-06-11T20:36:54.877 に答える