Reputation: 11
I'm setting up a gRPC client. The scenario is I have a REST API that then calls backend services using gRPC Code First. But I can't figure out how to I can inject a mock gRPC service so I can test the code calling the gRPC service. Ideally, I'd like to setup the gRPC service in program.cs then inject it into the class library code but am open to other solutions. Any ideas?
Note the client is .Net 6 Web API.
Upvotes: 1
Views: 89
Reputation: 104692
You can utilize WebApplicationFactory<TEntryPoint>
for that (see docs):
Ideally you'd have the actual implementation of your service use an underlying IRepository
etc. which you can setup with Mock.
Shared code:
using ProtoBuf.Grpc;
using System.Runtime.Serialization;
using System.ServiceModel;
namespace GrpcExperiments.Shared;
[DataContract]
public class HelloReply
{
[DataMember(Order = 1)]
public string? Message { get; set; }
}
[DataContract]
public class HelloRequest
{
[DataMember(Order = 1)]
public string? Name { get; set; }
}
[ServiceContract]
public interface IGreeterService
{
[OperationContract]
Task<HelloReply> SayHelloAsync(HelloRequest request);
}
Server code:
using ProtoBuf.Grpc;
using GrpcExperiments.Shared;
public class GreeterService : IGreeterService
{
public Task<HelloReply> SayHelloAsync(HelloRequest request)
{
return Task.FromResult(
new HelloReply { Message = $"Hello {request.Name}" });
}
}
Test code:
using Gnc = Grpc.Net.ClientFactory;
[Fact]
public async Task TestGreeterService()
{
using var webApp = new WebApplicationFactory<Program>();
// optional setup of IRepository or other underlying business-layer
// GreeterService will then have a constructor that takes the IRepository
webApp.WithWebHostBuilder(hostBuilder =>
hostBuilder.ConfigureServices(services =>
{
var repositoryMock = new Mock<IRepository>();
repositoryMock.Setup(x => x.GetById(1)).Returns(...);
services.AddSingleton(repository.Object);
}));
var services = new ServiceCollection();
services
.AddCodeFirstGrpcClient<IGreeterService>(clientFactoryOptions =>
{
clientFactoryOptions.Address = webApp.Server.BaseAddress;
clientFactoryOptions.ChannelOptionsActions.Add(option =>
option.HttpHandler = webApp.Server.CreateHandler());
});
using var serviceProvider = services.BuildServiceProvider();
var factory = serviceProvider.GetRequiredService<Gnc.GrpcClientFactory>();
var client = factory.CreateClient<IGreeterService>(nameof(IGreeterService));
var reply = await client.SayHelloAsync(
new HelloRequest { Name = "GreeterClient" });
Assert.Equal("Hello GreeterClient", reply.Message);
}
Upvotes: 0