单元测试调用含grpc.SetHeader的函数失败,求非Mock解决方法
问题描述
我有一个向gRPC Header中添加内容的函数:
func Dummy(ctx context.Context, request *service.Request) error { err := grpc.SetHeader(ctx, metadata.Pairs("key", "value")) return err }
该函数在服务正常调用时运行正常,但编写单元测试用例时总是报错:
rpc error: code = Internal desc = grpc: failed to fetch the stream from the context context.TODO
测试代码如下:
func TestDummy() { ctx := context.TODO() err := Dummy(ctx, &service.Request{}) }
我不想通过Mock grpc.SetHeader来解决,请问还有其他办法吗?
解决方案
问题根源在于grpc.SetHeader需要从上下文里获取gRPC服务端流(ServerStream)实例,而context.TODO()是无任何gRPC相关信息的空上下文,因此触发报错。可以通过构造包含mock服务端流的上下文来解决,无需Mockgrpc.SetHeader本身。
- 定义Mock ServerStream结构体
实现grpc.ServerStream接口的必要方法,至少覆盖SetHeader、Context等核心方法:
type mockServerStream struct { ctx context.Context header metadata.MD } func (m *mockServerStream) SetHeader(h metadata.MD) error { m.header = h return nil } func (m *mockServerStream) SendHeader(h metadata.MD) error { return nil } func (m *mockServerStream) SetTrailer(h metadata.MD) {} func (m *mockServerStream) Context() context.Context { return m.ctx } func (m *mockServerStream) SendMsg(msg interface{}) error { return nil } func (m *mockServerStream) RecvMsg(msg interface{}) error { return nil }
- 构造带Mock Stream的测试上下文
使用grpc.NewContextWithServerStream将mock流注入上下文,再传入测试函数:
func TestDummy(t *testing.T) { baseCtx := context.Background() mockStream := &mockServerStream{ctx: baseCtx} // 生成包含gRPC服务端流的上下文 ctx := grpc.NewContextWithServerStream(baseCtx, mockStream) err := Dummy(ctx, &service.Request{}) if err != nil { t.Fatalf("Dummy函数执行失败: %v", err) } // 可选:验证Header是否正确设置 if len(mockStream.header["key"]) == 0 || mockStream.header["key"][0] != "value" { t.Errorf("期望Header的key值为'value',实际得到'%s'", mockStream.header["key"][0]) } }
这种方式模拟了真实的gRPC服务端上下文环境,既避免了Mock核心方法,又能验证Header的设置结果,更贴近实际运行场景。
内容的提问来源于stack exchange,提问作者Aman RAJ
相关产品推荐
相关产品推荐

