【问题标题】:How can I verify a MySQL row creation date in a JavaScript integration test?如何在 JavaScript 集成测试中验证 MySQL 行创建日期?
【发布时间】:2020-04-08 14:28:00
【问题描述】:

我正在为与 MySQL 数据库一起使用的 Node 数据访问模块中的“create”方法编写集成测试。我们的 MySQL 表有一个created_at 字段,类型为timestamp,默认为CURRENT_TIMESTAMP。假设我的桌子看起来像这样:

CREATE TABLE `some_table` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `column1` varchar(255) DEFAULT NULL,
  `column2` int(11) DEFAULT NULL,
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
)

我想做的是测试created_at 字段是否按预期设置,例如,它是否相同或在测试开始执行之后。我正在尝试使用 Moment 的 isSameOrAfter 和它的 utc() 解析能力,但我无法弄清楚。假设我的测试看起来像这样:

test('created_at is set on creation', async () => {
  // must use UTC since CURRENT_TIMESTAMP is UTC
  const now = moment.utc();
  // newObject is a POJO of the newly created row in some_table
  const newObject = await someTableLib.create(args);
  // this does not work for some reason
  expect(moment.utc(newObject.created_at).isSameOrAfter(now)).toBe(true);
})

我也试过不使用utc()来解析数据库日期:

expect(moment(newObject.created_at).isSameOrAfter(now)).toBe(true);

如何最好地测试数据库是否按预期设置 created_at

编辑
我在输入一些 console.log() 语句时看到的一些示例值(尽管我不确定如何最好地比较 console.log 中的 Moment 值):

console.log(newObject.created_at);
// 2020-04-08T14:50:46.000Z
console.log(moment.utc(newObject.created_at).format('YYYY-MM-DD HH:mm:ss');
// 2020-04-08 14:50:46
console.log(now.format('YYYY-MM-DD HH:mm:ss');
// 2020-04-08 14:50:46

编辑 2
我现在完全糊涂了。如果我格式化矩对象,然后将它们重新初始化为矩对象,然后比较它们,它可以工作:

const testStart = moment(now.format('YYYY-MM-DD HH:mm:ss'));
const created = moment(moment.utc(newObject.created_at).format('YYYY-MM-DD HH:mm:ss'));
expect(created.isSameOrAfter(testStart)).toBe(true);  // this passes!!

【问题讨论】:

  • 您是否尝试记录 now 和 created_at 的值?这将使您对服务器和客户端之间的时区差异有一个很好的了解。另一个建议是尽量避免这样的测试。最好依靠 DB 库的返回值来评估事务的成功或失败。就像一些 DB 处理程序返回新创建记录的 ID,而另一些返回 true 或 false。
  • @VPaul 我现在正在这样做,并将使用示例值编辑 OP。
  • @VPaul 你是对的,也许我不应该测试这个。但现在我真的很好奇为什么它不工作并且很难放手:)
  • 我想我知道为什么会发生这种情况。您的服务器和客户端时区可能存在毫秒级的差异。因此,您从与客户端不同步的后端获取结果,并且时刻正在比较直到最后一个可用部分,这显示了错误的结果。通过将isSameOrAfter 中的精度传递给分钟 IMO (momentjscom.readthedocs.io/en/latest/moment/05-query/…),它可能运行良好。
  • @VPaul 就是这样!如果我为isSameOrAfter 指定“分钟”或“秒”,它会工作,但如果没有,则会失败。谢谢!请发表您的评论作为答案,以便我投票和接受。

标签: mysql node.js jestjs momentjs


【解决方案1】:

服务器(数据库服务器)和客户端(应用程序服务器)时间似乎不匹配毫秒或一小部分。在这种情况下,似乎服务器的时间领先于客户端的时间,它总是返回created_at(来自服务器)小于now(来自测试用例中的客户端)。

为了解决这个问题,我们可以将精度传递给 moment 的 isSameOrAfter 函数作为“分钟”或“秒”,以便在比较两者时忽略较小的分数。请参阅文档 (https://momentjscom.readthedocs.io/en/latest/moment/05-query/05-is-same-or-after/) 了解如何将精度传递给此函数。

【讨论】:

    【解决方案2】:

    您可以尝试使用 MySQL(以秒为单位)和 javascript(以毫秒为单位)都支持的 unix 时间戳,而不是使用 momentjs

    test('difference in time should be within a second', () => {
      x = query("SELECT UNIX_TIMESTAMP(created_at) AS x FROM ...");
      expect(x).toBeCloseTo(Date.now() / 1000, 0);
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多