使用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
相关产品推荐
相关产品推荐

