【问题标题】:How can I mock Date.now multiple times concurrently如何同时模拟 Date.now 多次
【发布时间】:2020-10-03 19:54:33
【问题描述】:

我正在尝试实现自己的模拟日期函数,我希望它能够同时工作。

我认为最佳用法是:

mockDate(myFirstDate, async () => {
   // Here and only here Date.now() === myFirstDate
})

mockDate(mySecondDate, async () => {
   // Here and only here Date.now() === mySecondDate
})

// Outside Date.now is working as expected

这是我想要实现的最小失败代码示例:

async function mockDate(timestamp, callback) {
    const original_now = Date.now

    Date.now = function() {
        if (/* How can I check Date.now have been called inside callback */ true) return timestamp
        else return original_now()
    }

    await callback()

    Date.now = original_now
}

const wait = ms => new Promise(res => setTimeout(res, ms))

mockDate(1600000000000, async () => {
    await wait(100)
    const result = Date.now()
    if (result !== 1600000000000) throw new Error('Fail: 1600000000000')
}).catch(console.error)

mockDate(1650000000000, async () => {
    const result = Date.now()
    if (result !== 1650000000000) throw new Error('Fail: 1650000000000')
    await wait(200)
}).catch(console.error)

我的想法是检查if 内部是否可以检索callback 内部this.caller。不幸的是,访问this.caller 给我一个错误。

我也知道测试框架通常有串行模式,但我试图避免它。

【问题讨论】:

    标签: javascript node.js unit-testing mocking


    【解决方案1】:

    禁用严格模式或使用串行模式。

    【讨论】:

      【解决方案2】:

      这是一个可行的解决方案:

      async function mockDate(timestamp, callback) {
          const original_now = Date.now
      
          Date.now = function() {
              try {
                  let caller = arguments.callee.caller
                  while (caller !== callback && caller.caller) {
                      caller = caller.caller
                  }
                  return caller === callback
                      ? timestamp
                      : original_now()
              } catch {
                  return original_now()
              }
          }
      
          await callback()
      
          Date.now = original_now
      }
      

      此解决方案的一个主要缺点是您不能使用箭头功能

      mockDate(date, async () => {
          const date1 = (function() { return Date.now() })() // Date is mocked
      
          const date2 = (() => Date.now())() // Date wont be mocked
      })
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-11-02
        相关资源
        最近更新 更多