我正在为一个angularjs工厂写一些测试,但有些期望无效,我真的不知道为什么。
这是我的工厂(部分)。 'use strict';
angular.module('myAppMod')
.factory('Person', function(BaseModel) {
return BaseModel.extend({
get fullname() {
var name = [];
if (this.first_name) {
name.push(this.first_name);
}
if (this.person_extra && this.person_extra.middle_name) {
name.push(this.person_extra.middle_name);
}
if (this.last_name) {
name.push(this.last_name);
}
return name.join(' ');
}
});
});
和Jasmine测试:
var p;
beforeEach(function() {
p = new Person({
first_name: 'first_name',
person_extra: {
middle_name: 'middle_name',
media_item_id: null
},
last_name: 'last_name',
security_level: 'security_level'
}, true);
});
it("has a fullname", function() {
expect(p.fullname).toEqual('first_name middle_name last_name');
});
p.fullname
正在返回""
(空字符串),而在工厂中console.log(this.first_name)
正在undefined
。
非常感谢任何帮助。 提前谢谢
答案 0 :(得分:6)
它无效,因为您通过get fnName() { }
方法使用 getter 速记(extend
)。 getter的 this
是匿名对象本身,不继承Backbone模型的方法和属性,而函数属性中的this
做。我做了codepen that illustrate your problem。
也就是说,如果这是你的模型
var Model = BaseModel.extend({
get isBackboneModelThroughGetter() {
return !!this.get;
},
isBackboneModel: function() {
return !!this.get;
},
});
然后,Model的一个实例将使该测试通过:
it('should make you wonder', function() {
var model = new Model();
expect(model.isBackboneModel()).toBe(true);
expect(model.isBackboneModelThroughGetter).not.toBe(true);
});
因此,要使您的工厂工作,您将需要:
this.get('propertyName')
而不是this.propertyName
full_name : function() { /*...*/ }
而不是get full_name() { /* ... */ }
model.full_name
; model.full_name()
醇>
答案 1 :(得分:1)
我假设您使用的是内置angular.extend
。 angular.extend
不复制getter和setter。自2014年8月12日起,GitHub就此特定主题进行了an open issue。
至于为什么它仍未实施:
Angular公开了它在内部使用的一些辅助函数。
extend
,copy
和其他许多人都是这种情况。还有其他专门研究这些功能的库,保留它们的功能 专注于那里,可以做得更好。大多数用户的最佳利益是使这些辅助函数变大或变慢,因为这些函数在内部使用,并且该方向的任何更改都会对下载大小和性能产生直接影响。与此同时,需要最准确版本的应用程序应该更好地与其他库一起提供。
有很多方法可以解决这个问题。 decaf.js
提供了一个适用于大多数情况的示例实现。 GitHub可能是一个更好的环境,可以深入研究它们的代码,但它归结为:
function extend (me) {
var args = Array.prototype.slice.call(arguments, 1);
decaf.each(args, function (o) {
for (var key in o) {
if (o.hasOwnProperty(key)) {
var desc = Object.getOwnPropertyDescriptor(o, key);
var g = desc.get;
var s = desc.set;
if (g || s) {
Object.defineProperty(me, key, { get: g, set: s, enumerable: true });
} else {
me[key] = o[key];
}
}
}
});
return me;
}