如何在单元测试中模拟 moment.utc() 函数?

19

我刚开始使用Node,现在正在编写一些单元测试。对于前几个函数,它们运行良好,但是现在我遇到了一个包含moment.utc() 的函数。我的功能简化版本如下:

function calculate_x(positions, risk_free_interest){
    let x = 0;
    for (let position of positions) {
        let expiry_in_years = get_expire_in_years(moment.utc());
        if (expiry_in_years > 0){
            let pos_x = tools.get_x(expiry_in_years, risk_free_interest);
            x += pos_x;
        }
    }

    return x;
}

我试图使用基本的 node assert 测试库来测试这个:

"use strict";
const assert = require('assert');
let positions = [{this: 'is', a: 'very', large: 'object'}]; 
assert.strictEqual(calculate_x(positions, 1.8), 1.5);

由于运行时间(因此结果)始终不同,因此这将始终失败。

在Python中,我可以设置模拟类和对象。在Node中是否有一种方法可以解决这个问题,而无需将moment.utc()作为参数传递给calculate_x()函数?


2
你需要类似于更改时间源这样的东西吗? - VincenzoC
sinon是一个非常棒的测试库,特别适用于Node环境。你可以在其中模拟/修改定时器。http://sinonjs.org/releases/v4.0.1/fake-timers/ - Johannes Merz
{btsdaf} - kramer65
{btsdaf} - VincenzoC
3个回答

40

Moment让你可以更改时间来源

如果您想更改Moment看到的时间,您可以指定一个返回自Unix纪元(1970年1月1日)以来毫秒数的方法。

默认值为:

moment.now = function () {
    return +new Date();
}

当调用moment()时将使用此选项,当从format()省略标记时将使用当前日期。通常情况下,任何需要当前时间的方法都在幕后使用此选项。

因此,您可以重新定义moment.now以在执行moment.utc()时获取自定义输出。


1
如果您只想覆盖utc函数而其他方法都无效,请尝试在测试套件中添加以下内容。
moment.prototype.utc = sinon.stub().callsFake(() => new Date(1970, 1, 1, 0, 0));

或者

moment.prototype.utc = jest.fn().mockReturnValue(new Date(1970, 1, 1, 0, 0));

1
const moment = require('moment'); 
const time = moment().valueOf();
moment.now = jest.fn().mockReturnValue(time);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接