首页 > 解决方案 > 是否可以编写测试来测试记录的键的顺序

问题描述

Logrus 按字母顺序记录键,这是我想要和需要的,但我想编写一个测试以确保它不会更改,我尝试添加挂钩,但我认为我无法使用自定义访问完整日志我添加的上下文我WithFields只能获取消息记录示例

func TestSomething(t*testing.T){
  logger, hook := test.NewNullLogger()
  logger.WithField("correlationId","123").WithField("id","1").Info("hello")

  assert.Equal(t, 1, len(hook.Entries))
  assert.Equal(t, logrus.(Level, hook.LastEntry().Level)
  assert.Equal(t, "Hello", hook.LastEntry().Message)

  hook.Reset()
  assert.Nil(t, hook.LastEntry())
}

我想测试message之前t在输出中出现的内容

log.SetFormatter(&log.JSONFormatter{
        FieldMap: log.FieldMap{
            log.FieldKeyMsg: "message",
            log.FieldKeyTime: "t",
        },
    })
    logger := log.WithFields(
        log.Fields{
            "id":        context.id,
            "correlationId":       context.CorrelationId,
        },

标签: gologrus

解决方案


Logrus 按字母顺序记录键

不,它实际上没有。A实际上只是一个标准的围棋地图(如您在此处FieldMap所见)。同一个文件显示了如何处理字段映射的 JSON 编组。那里没有任何迹象表明正在进行任何特定的键排序。

很有可能,由于映射键的散列方式,在您的特定情况下,在您的平台上,使用您的 logrus 和 go 编译器的特定版本,输出似乎是按字母顺序排列的。但是,不能保证永远都是这样。如果您为不同的架构/操作系统(GOARCHGOOS)编译相同的代码,输出可能不一样。事情现在看起来是按字母顺序排列的,但这只是巧合。编写测试以确保您的运气没有耗尽不是测试的重点。

根据定义,映射是无序的数据结构。如果您希望日志输出按字母顺序排列,那么您可以为 logrus 编写自己的格式化程序,遍历字段映射,将所有键(作为字符串)添加到切片,对所述切片进行排序,然后遍历排序后的键以按字母顺序打印出按键。再说一次,我真的很想知道你的用例是什么来证明这样的事情。


是的,仔细检查后,似乎该encoding/json包实际上将映射编组为 JSON 对象,并且对键进行了排序

映射值编码为 JSON 对象。映射的键类型必须是字符串、整数类型或实现encoding.TextMarshaler。通过应用以下规则对映射键进行排序并用作 JSON 对象键,但要遵守上面为字符串值描述的 UTF-8 强制

这很好,并且只要标准库没有改变(或者你不决定将它换成一些行为不同的替代品),你应该很好。使用不同的格式化程序时,也不能保证这种行为。您的一开始是确保更换日志记录包不会破坏这种行为。在这种情况下,您正在测试错误的东西......它不是日志记录包本身,而是您正在使用的 json 编码包(编组器)。

您基本上是在寻找一种方法来测试是否有人将替代编组包插入您正在使用的外部包中。如果下一个版本的 logrus 最终切换到类似ffjson的包,那么您的测试将会失败,尽管您只是改变了日志包的版本,并且除此之外没有进行任何其他更改。单元测试并不是执行此操作的最佳方法。你可以维护你自己的 logrus 包的分支,或者只是在你的 go.mod 文件中锁定一个已知的好版本,然后就结束了。


推荐阅读