我是编写单元测试的新手。
我的函数如下所示:
getData() {
return this.parameters.map(p => {
return {
name: p.name,
items: p.items.map(item => {
const toTime = item.hasOwnProperty('end') ? moment.utc(item.end._d).unix() : null;
const fromTime = item.hasOwnProperty('start') ? moment.utc(item.start._d).unix() : null;
return {
id: item.id,
fromTime: fromTime,
toTime: toTime,
};
}),
};
});
}
到目前为止,我的 Jasmine 测试如下所示:
describe('getData()', function() {
it('should return json data', function() {
$ctrl.parameters = [{
name: 'test',
items: [{
id: 1,
fromTime: null,
toTime: null
}, {
id: 13,
fromTime: null,
toTime: null
}]
}];
expect($ctrl.getData()).toEqual([{
name: 'test',
items: [{
id: 1,
fromTime: null,
toTime: null
}, {
id: 13,
fromTime: null,
toTime: null
}]
}]);
});
});
此测试正在运行/通过,但如您所见,我没有测试使用 Moment.js 的三元 if/else。基本上三元组所做的是检查项目是否包含名为 start
/end
的属性,如果包含,将该值转换为纪元/Unix 时间戳并将其分配给 toTime
或 fromTime
。
因此,如果项目有一个名为 end 的属性,其值为 'Sat Oct 31 2015 00:00:00 GMT+0000 (GMT)'
,那么它将被转换为 ' 1446249600'
并分配给 toTime
。
如何为它编写测试?
最佳答案
最简单的选择是为输入手动构建几个示例日期。例如:
$ctrl.parameters = [{
name: 'test',
items: [{
id: 1,
start: moment.utc('2017-01-01T01:00:00'),
end: moment.utc('2017-01-01T06:00:00')
}, {
id: 13,
start: moment.utc('2017-01-02T08:00:00'),
end: null
}]
}];
(注意在上面的例子中,我把fromTime
和toTime
分别改成了start
和end
,因为这就是 getData
所期望的输入。)
然后计算出它们的 unix 时间戳。您可以在外部执行此部分 - 例如,我刚刚在 moment.js 网站上打开浏览器开发人员工具 (F12),在控制台中评估以下语句,并获取时间戳值:
moment.utc('2017-01-01T01:00:00').unix()
moment.utc('2017-01-01T06:00:00').unix()
moment.utc('2017-01-02T08:00:00').unix()
最后,回到单元测试,只需验证时间戳是否与预期值匹配:
expect($ctrl.getData()).toEqual([{
name: 'test',
items: [{
id: 1,
fromTime: 1483232400,
toTime: 1483250400
}, {
id: 13,
fromTime: 1483344000,
toTime: null
}]
}]);
或者,如果您不想在单元测试中使用硬编码时间戳,则可以将每个示例日期存储在其自己的变量中(例如,start1
、end1
) ,然后与例如 start1.unix()
进行比较:
// Arrange
const start1 = moment.utc('2017-01-01T01:00:00');
const end1 = moment.utc('2017-01-01T06:00:00');
const start2 = moment.utc('2017-01-02T08:00:00');
$ctrl.parameters = [{
name: 'test',
items: [{
id: 1,
start: start1,
end: end1
}, {
id: 13,
start: start2,
end: null
}]
}];
// Act
const result = $ctrl.getData();
// Assert
expect(result).toEqual([{
name: 'test',
items: [{
id: 1,
fromTime: start1.unix(),
toTime: end1.unix()
}, {
id: 13,
fromTime: start2.unix(),
toTime: null
}]
}]);
这很好,因为单元测试旨在测试您的代码,而不是 moment.js。这取决于你。
另请注意,我使用的是 Arrange-Act-Assert组织测试的模式。同样,这取决于您,但是一旦您的单元测试开始变得复杂,这往往会让事情更容易理解。
无论哪种方式,您都需要更改在 getData
方法中计算 toTime
和 fromTime
的方式,因为编写的代码不会如果您为 start
或 end
传入 null
,则工作。特别是,如果您为 start
传入一个 null
值,item.hasOwnProperty('start')
将返回 true,但它会出错因为它试图评估 item.start._d
。
相反,我建议将这两行更改为以下内容:
const toTime = item.end ? moment.utc(item.end._d).unix() : null;
const fromTime = item.start ? moment.utc(item.start._d).unix() : null;
我还建议不要使用 moment 对象的 _d
属性,因为这是一个内部(私有(private))变量。由于 start
和 end
已经是 moment 对象,您可以改为这样做:
const toTime = item.end ? item.end.unix() : null;
const fromTime = item.start ? item.start.unix() : null;
此处提供了包含上述所有建议更改的完整 jsbin 示例:
https://jsbin.com/xuruwuzive/edit?js,output
请注意,必须进行一些调整才能使其在 AngularJS 的上下文之外运行(使 getData 成为一个独立函数,直接接受其参数,而不是通过 $ctrl
)。
关于javascript - 使用 moment.js 进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41144348/