如何为依赖其他gRPC服务的ASP.NET Core gRPC服务编写单元测试?
解决方法
1. 直接引用API项目的生成客户端
直接给测试项目添加对Users.Api项目的项目引用,这样就能直接访问Users.Api.UsersProtoClient类。不过要注意,这种方式会让测试项目依赖API项目的编译输出,得确保API项目能正常编译。
2. 统一gRPC客户端的命名空间
修改proto文件所在项目的.csproj配置,让测试项目生成的客户端和API项目用同一个命名空间。在API项目的.csproj里,给proto文件加上命名空间指定:
<ItemGroup> <Protobuf Include="Protos\users.proto" GrpcServices="Client"> <Namespace>Users.Api</Namespace> </Protobuf> </ItemGroup>
这样测试项目生成的客户端就会落在Users.Api命名空间下,和IdentityService需要的类型完全匹配。
3. 抽象客户端接口(推荐)
给gRPC客户端定义一个抽象接口,让IdentityService依赖接口而不是具体的客户端实现。比如:
public interface IUsersApiClient { // 照着UsersProtoClient的方法签名定义接口方法 Task<UserResponse> GetUserByIdAsync(GetUserRequest request, CallOptions options = default); }
然后在API项目里写个适配器类,实现这个接口并包装UsersProtoClient:
public class UsersApiClientAdapter : IUsersApiClient { private readonly UsersProtoClient _client; public UsersApiClientAdapter(UsersProtoClient client) { _client = client; } public Task<UserResponse> GetUserByIdAsync(GetUserRequest request, CallOptions options = default) { return _client.GetUserByIdAsync(request, options); } }
最后修改IdentityService的构造函数,改成依赖IUsersApiClient:
public class IdentityService (IUsersApiClient usersApiClient, IdentityDbContext dbContext, TimeProvider timeProvider) : IdentityProto.IdentityProtoBase { // ... }
这样测试的时候,直接用Moq模拟IUsersApiClient就行,完全不用管具体的客户端类型,还能解耦服务间的依赖,代码更易维护。
内容的提问来源于stack exchange,提问作者Matin
相关产品推荐
相关产品推荐

