2

我创建了一个返回构造函数的工厂。构造函数包括一个观察实例属性的观察者。在测试中更改该属性时,不会触发观察者。在测试之外,它被解雇了。$rootScope.$apply 似乎没有帮助。

这是一个 jsfiddle,其中包含我的代码和测试的简化版本。

http://jsfiddle.net/2Ny8x/234/

//--- CODE --------------------------
(function (angular) {
    var myApp = angular.module('myApp', []);

    myApp.factory('MyObject', function($rootScope) {
        function MyObject() {
            this.prop = 5;
            this.watcherCallback = angular.noop;

            $rootScope.$watch(this.prop, this.watcherCallback);
        }

        return MyObject;
    });
})(angular);


// ---SPECS-------------------------
describe('MyObject', function () {
    beforeEach(module('myApp'));

    var MyObject, rootScope;
    beforeEach(inject(function (_MyObject_, $rootScope) {
        MyObject = _MyObject_;
        rootScope = $rootScope;
    }));

    it('calls the watcher when "prop" updates', function() {
        var newObj = new MyObject();
        spyOn(newObj, 'watcherCallback');

        newObj.prop = 10;
        rootScope.$apply();

        expect(newObj.watcherCallback).toHaveBeenCalled();
    });
});

为什么观察者不开火?

4

1 回答 1

2
var newObj = new MyObject();

这分配noopnewObj.watcherCallback。并将newObj.watcherCallback(so, noop) 注册为观察者回调。

spyOn(newObj, 'watcherCallback');

这由另一个函数替换newObj.watcherCallback,它允许您知道何时调用这个新的 spy 函数。但它不会将此 spy 函数注册为 rootScope 的观察者回调。什么是寄存器是原来的:noop.

因此,当您更改属性的值并调用$apply()时,rootScope 仍然具有对该noop函数的引用并调用它。你的间谍不知道。

如果您在构造函数中这样做,它应该可以正常工作:

var that = this;
$rootScope.$watch(this.prop, function() {
    that.watcherCallback();
});
于 2015-02-16T21:22:52.247 回答