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

使用Golang和Mockery测试gRPC服务时Mock失败导致超时问题

问题分析与解决

核心原因

t.FailNow() 只会终止调用它的那个goroutine,而非整个测试进程。在你的场景中:

  • Mock的Create方法是在gRPC服务器的请求处理goroutine中被调用的,因此调用t.FailNow()仅会终止这个处理goroutine。
  • 测试主goroutine此时正阻塞在client.Create(ctx, ...)的调用上,等待服务器返回响应——但处理请求的goroutine已被终止,不会返回任何响应,主goroutine会一直等到gRPC调用超时才退出,defer s.Stop()自然也不会提前执行。

解决方案

1. 给gRPC客户端调用设置超时上下文

修改客户端调用的上下文,添加超时时间,这样即使服务器端的处理goroutine挂了,客户端也会在超时后主动返回,触发defer的Stop方法,让测试及时退出:

ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
val, err := client.Create(ctx, &CreateMessage{12, "foobar"})

2. 主动检查Mock的断言状态

改用t.Fail()标记测试失败(不会终止goroutine),然后在客户端调用后主动检查Mock的预期是否都被满足,让主goroutine主动发现失败并退出:

// 客户端调用后立即检查Mock的预期是否达成
mockInterface.AssertExpectations(t)

当Mock的预期未被满足时,AssertExpectations(t)会在主goroutine中调用t.FailNow(),直接终止测试主goroutine,触发defer s.Stop()。

3. 优化gRPC Server的Serve goroutine错误处理

当前Serve()方法中的goroutine会在Server.Serve()返回任何错误时调用s.t.Fail(),但Server.Stop()触发的退出会返回grpc.ErrServerStopped,这属于正常终止,应该排除这种情况:

go func() {
    if err := s.Server.Serve(s.Lis); err != nil && err != grpc.ErrServerStopped {
        s.t.Fatalf("gRPC server failed to serve: %v", err)
    }
}()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 22:57:26