Javascript Angularjs和Jasmine:使用同一服务的多个实例进行测试
我目前正在阅读一本名为《使用AngularJS掌握Web应用程序开发》的书,其中一个例子中有一个名为“聚合回调”的测试 我遇到问题的示例包含Person对象: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
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中的函数和对象不是吗?