应使用 errors.is 或 errors.as 检查错误类型:errors.is(err, io.eof) 验证错误链中是否存在目标错误;errors.as(err, &e) 断言是否为特定自定义错误类型,避免直接比较 error 值。
如何用 testify/assert 检查错误是否为特定类型
Go 的错误是值,不是异常,所以测试时不能靠 panic 捕获,而要直接比对 error 值本身或其底层类型。常见误区是用 assert.Equal(t, err, io.EOF) —— 这在多数情况下失败,因为 io.EOF 是一个地址固定的变量,而函数返回的错误可能是新构造的、语义相同但地址不同的实例。
正确做法是用类型断言或 errors.Is(Go 1.13+):
if !errors.Is(err, io.EOF) {
t.Fatal("expected io.EOF")
}
// 或用 testify:
assert.True(t, errors.Is(err, io.EOF))
-
errors.Is判断错误链中是否存在目标错误(支持包装),适合检查标准错误如io.EOF、os.ErrNotExist - 若需验证自定义错误类型(如实现了
MyError结构体),用errors.As:var e *MyError; assert.True(t, errors.As(err, &e)) - 避免直接比较
err == someErr,除非你明确控制了错误实例的复用(极少见)
如何模拟并触发特定错误路径(如网络超时、文件不存在)
真实调用 os.Open 或 http.Get 会引入外部依赖,导致测试不稳定、慢、不可控。必须将底层依赖抽象为接口,并在测试中注入返回预设错误的 mock 实现。
例如,封装文件操作: