2016-12-14 166 views
12

我是编写单元测试的新手,需要一些帮助测试函数的一部分。使用moment.js进行单元测试

我的功能看起来像这样...

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, 
       }; 
      }), 
     }; 
    }); 
} 

,到目前为止,我的测试看起来像这样(茉莉)

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的属性,如果有,请将该值转换为epoch/unix时间戳,并将其分配给toTimefromTime。所以如果物品有一个叫做end的属性,其值为'Sat Oct 31 2015 00:00:00 GMT+0000 (GMT)',那么它将被转换为'1446249600'并分配给toTime

希望这可以解释它!我不确定如何为它编写测试,并希望得到任何帮助/建议。

回答

6

最简单的选择是仅为输入手动构建几个示例日期。例如:

$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 

    }] 
}]; 

(请注意,在上面的例子中,我改变fromTimetoTime分别startend,因为这是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),然后与例如比较10:

// 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方法计算toTimefromTime,因为书面如果你null通过对两种startend将无法​​正常工作的代码。特别是,item.hasOwnProperty('start')将返回true,如果您通过startnull值,但它会错误,因为它会尝试评估item.start._d。 相反,我建议改变那些2线为以下:

const toTime = item.end ? moment.utc(item.end._d).unix() : null; 
const fromTime = item.start ? moment.utc(item.start._d).unix() : null; 

我也建议不要使用的时刻对象的属性_d,因为这是一个内部(私有)变量。由于startend已经瞬间的对象,你可以改为能够只是做到这一点:

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)。

+0

谢谢!它的工作。也谢谢你的样品! –