Javascript Angularjs和Jasmine:使用同一服务的多个实例进行测试

Javascript Angularjs和Jasmine:使用同一服务的多个实例进行测试,javascript,angularjs,tdd,jasmine,jasmine-node,Javascript,Angularjs,Tdd,Jasmine,Jasmine Node,我目前正在阅读一本名为《使用AngularJS掌握Web应用程序开发》的书,其中一个例子中有一个名为“聚合回调”的测试 我遇到问题的示例包含Person对象: var Person = function(name, $log) { this.eat = function(food) { $log.info(name + ' is eating delicious ' + food); }; this.beHungry = function(reas

我目前正在阅读一本名为《使用AngularJS掌握Web应用程序开发》的书,其中一个例子中有一个名为“聚合回调”的测试

我遇到问题的示例包含Person对象:

var Person = function(name, $log) {

    this.eat = function(food) {

        $log.info(name + ' is eating delicious ' + food);

    };

    this.beHungry = function(reason) {

        $log.warn(name + ' is hungry because: ' + reason);

    };

};
名为“餐厅”的对象:

var Restaurant = function($q, $rootScope) {

    var currentOrder;

    return {

        takeOrder : function(orderedItems) {

            currentOrder = {

                deferred : $q.defer(),
                items : orderedItems

            };

            return currentOrder.deferred.promise;

        },

        deliverOrder : function() {

            currentOrder.deferred.resolve(currentOrder.items);
            $rootScope.$digest();

        },

        problemWithOrder : function(reason) {

            currentOrder.deferred.reject(reason);
            $rootScope.$digest();

        }

    };

};
最后是聚合回调的测试:

it('should allow callbacks aggregation', function() {

    var pizzaPid = new Restaurant($q, $rootScope);

    var pizzaDelivered = pizzaPid.takeOrder('Margherita');

    pizzaDelivered.then(pawel.eat, pawel.beHungry);
    pizzaDelivered.then(pete.eat, pete.beHungry);

    pizzaPid.deliveryOrder();

    expect($log.info.logs).toContain(['Pawel is eating delicious Margherita']);
    expect($log.info.logs).toContain(['Pete is eating delicious Margherita']);

});
正如您所看到的,测试没有显示如何向测试中添加/注入项,我对TDD的概念基本上是陌生的

我最后做的是将这些全局对象转换为服务和工厂:

angular.module('myApp', [])

    .service('Person', function(personName, $log) {

        this.eat = function(food) {

            $log.info(personName + ' is eating delicious ' + food);

        };

        this.beHungry = function(reason) {

            $log.warn(personName + ' is hungry because: ' + reason);

        };

    })

    .factory('Restaurant', function($q, $rootScope) {

        var currentOrder;

        return {

            takeOrder : function(orderedItems) {

                currentOrder = {

                    deferred : $q.defer(),
                    items : orderedItems

                };

                return currentOrder.deferred.promise;

            },

            deliverOrder : function() {

                currentOrder.deferred.resolve(currentOrder.items);
                $rootScope.$digest();

            },

            problemWithOrder : function(reason) {

                currentOrder.deferred.reject(reason);
                $rootScope.$digest();

            }

        };

    });
但现在,我正在为在测试中表示“pawel”和“pete”的多个服务实例而挣扎:

describe('Person and Restaurant tests', function() {

    var Person;
    var Restaurant;

    var $q;
    var $rootScope;
    var $log;




    beforeEach(function() {


        module('myApp');

        module(function($provide) {

            $provide.value('personName', 'Pawel');

        });

        inject(function(_Person_, _Restaurant_, _$q_, _$rootScope_, _$log_) {

            Person = _Person_;
            Restaurant = _Restaurant_;

            $q = _$q_;
            $rootScope = _$rootScope_;
            $log = _$log_;

        });



    });


    it('should allow callbacks aggregation', function() {

        var pizzaDelivered = Restaurant.takeOrder('Margherita');

        // here's where the problem is
        // with current set up I can only call it as
        // pizzaDelivered.then(Person.eat, Person.beHungry);        
        pizzaDelivered.then(pawel.eat, pawel.beHungry);
        pizzaDelivered.then(pete.eat, pete.beHungry);

        Restaurant.deliveryOrder();

        expect($log.info.logs).toContain(['Pawel is eating delicious Margherita']);
        expect($log.info.logs).toContain(['Pete is eating delicious Margherita']);

    });


});

正如我所说,我是新手,希望能得到一些帮助。

为什么测试只允许

pizzaDelivered.then(Person.eat, Person.beHungry)
是因为您创建了个人服务。在Angular中,服务是单例的。“人”的概念并不完全符合单身者的概念(即,在任何给定时间可以有多人),但可以在您的应用程序中使用,如下所示:

app = app.module('app', [])
  .controller('chicago', function($scope, $log) {

      $scope.family = [
         new Person('henry', $log),
         new Person('me', $log),
         new Person('you', $log)
       ];

   });
你应该按照书中的定义离开这个人和餐馆。 我相信这是本书的意图,因为 在该定义中有唯一的代码行:

$rootScope.$digest();
这一行调用angular的摘要循环。它基本上贯穿了所有这些内容,并使用在其上下文中发生的任何更改来更新DOM和视图。例如 如果html绑定到$scope模型:

<div ng-model='name'> {{ name }} </div>
我注意到的一件事是,你说这本书的人物和餐厅是全球性的对象,但它们不是。它们具有全局函数/构造函数

这会让你的测试通过

总的来说,我相信这本书教给你的是如何使用angular之外的代码。在许多实际应用程序中,您几乎无法单独使用angular js代码。很多时候,你必须使用第三方代码,如谷歌地图、矩等

未来需要记住的事情:
我相信在未来的angular版本(2.0)中,该项目将进一步抽象$digest循环并使用Observe()fn

为什么测试只允许

pizzaDelivered.then(Person.eat, Person.beHungry)
是因为您创建了个人服务。在Angular中,服务是单例的。“人”的概念并不完全符合单身者的概念(即,在任何给定时间可以有多人),但可以在您的应用程序中使用,如下所示:

app = app.module('app', [])
  .controller('chicago', function($scope, $log) {

      $scope.family = [
         new Person('henry', $log),
         new Person('me', $log),
         new Person('you', $log)
       ];

   });
你应该按照书中的定义离开这个人和餐馆。 我相信这是本书的意图,因为 在该定义中有唯一的代码行:

$rootScope.$digest();
这一行调用angular的摘要循环。它基本上贯穿了所有这些内容,并使用在其上下文中发生的任何更改来更新DOM和视图。例如 如果html绑定到$scope模型:

<div ng-model='name'> {{ name }} </div>
我注意到的一件事是,你说这本书的人物和餐厅是全球性的对象,但它们不是。它们具有全局函数/构造函数

这会让你的测试通过

总的来说,我相信这本书教给你的是如何使用angular之外的代码。在许多实际应用程序中,您几乎无法单独使用angular js代码。很多时候,你必须使用第三方代码,如谷歌地图、矩等

未来需要记住的事情:
我相信在未来的angular版本(2.0)中,该项目将进一步抽象$digest循环并使用Observe()fn

然而,有一件事-你说上面定义的对象不是全局的-从我(有限的)理解来看,在javascript中在任何其他对象之外实例化对象-或者在本例中在Angular之外使用变量赋值在全局命名空间中创建对象。我不在这儿吗?你能解释一下为什么你认为:var Person=function(name,$log){}不创建全局对象吗?@SpencerMark你说得对,Person在全局命名空间中。然而,人是一个函数,而不是一个对象。你让我怀疑我自己,因为我对JS是相当陌生的:但不是JS中的函数和对象吗?然而,有一件事-你说上面定义的对象不是全局的-从我(有限的)理解来看,在javascript中,在任何其他对象之外实例化该对象,或者在本例中,在Angular之外使用变量赋值在全局命名空间中创建一个对象。我不在这儿吗?你能解释一下为什么你认为:var Person=function(name,$log){}不创建全局对象吗?@SpencerMark你说得对,Person在全局命名空间中。然而,人是一个函数,而不是一个对象。你让我怀疑我自己,因为我对JS是相当陌生的:但是JS中的函数和对象不是吗?