如何测试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
相关产品推荐
相关产品推荐

