You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何测试zerolog日志器是否触发了error类型的日志事件?

问题分析与解决

核心问题1:Hook未捕获日志事件

你的LogError函数里每次都通过zerolog.New(os.Stderr)创建了全新的Logger实例,完全脱离了测试代码中添加hook的那个Logger。测试里的hook只绑定在你手动创建的testLogger上,但实际LogError根本没用到它,自然捕获不到任何日志。

核心问题2:无法访问zerolog.Event的内容

zerolog的Event结构体字段都是私有,不能直接读取。要获取事件里的错误、消息等内容,需要在hook中把事件编码为JSON(或其他格式),再解析成可访问的结构体。

完整修复方案

1. 重构LogError函数,依赖传入的Logger

不要在函数内部硬创建Logger,改为接收一个*zerolog.Logger参数,这样测试时可以传入带hook的Logger:

func LogError(logger *zerolog.Logger, err error, msg string) {
	logger.Err(err).Msg(msg)
}

2. 实现能捕获并解析日志事件的Hook

自定义Hook,在Run方法中将Event编码为JSON,再解析成自定义结构体,方便后续断言:

import (
	"bytes"
	"encoding/json"
	"errors"
	"os"
	"testing"

	"github.com/rs/zerolog"
)

type CapturedLog struct {
	Level   string `json:"level"`
	Message string `json:"message"`
	Error   string `json:"error"`
}

type LogCaptureHook struct {
	Captured []CapturedLog
}

func (h *LogCaptureHook) Run(e *zerolog.Event, level zerolog.Level, msg string) {
	var buf bytes.Buffer
	// 手动保留并填充关键字段,确保编码后能解析
	e.Level(level)
	e.Str("message", msg)
	e.Encode(&buf)

	var captured CapturedLog
	if err := json.Unmarshal(buf.Bytes(), &captured); err != nil {
		panic(err)
	}
	h.Captured = append(h.Captured, captured)
}

3. 编写正确的测试用例

创建带hook的Logger,传入LogError,然后断言捕获到的日志:

func TestLogError(t *testing.T) {
	hook := &LogCaptureHook{}
	testLogger := zerolog.New(os.Stderr).Hook(hook)

	testErr := errors.New("test error")
	LogError(&testLogger, testErr, "failed to do something")

	if len(hook.Captured) != 1 {
		t.Fatalf("expected 1 log entry, got %d", len(hook.Captured))
	}

	captured := hook.Captured[0]
	if captured.Level != "error" {
		t.Errorf("expected level 'error', got '%s'", captured.Level)
	}
	if captured.Message != "failed to do something" {
		t.Errorf("expected message 'failed to do something', got '%s'", captured.Message)
	}
	if captured.Error != "test error" {
		t.Errorf("expected error 'test error', got '%s'", captured.Error)
	}
}

额外说明

  • 如果你不想让LogError暴露Logger参数,可以通过全局Logger或者依赖注入的方式传递,比如在应用初始化时设置zerolog.DefaultContextLogger,然后LogError里用zerolog.Ctx(ctx).Err(err).Msg(msg),测试时替换默认Logger即可。
  • zerolog的Hook在Event被发送(调用Msg/Msgf等方法)时才会触发,确保你的日志调用最终调用了这些方法。

内容的提问来源于stack exchange,提问作者baitendbidz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 08:08:20