I am using the packages Grpc.Core and ProtoBuf.Grpc because I want to use both: Code-First gRPC with gRPC ClientFactory.
Now I have an interface of form Task<Response> MyMethod(Request request, CallContext context) with CallContext coming from ProtoBuf.Grpc.
In the implementation of the interface I get the authorized (calling) user like this:
var user = httpContext.User.Claims.Where(x => x.Type == JwtRegisteredClaimNames.Name).FirstOrDefault();
Now I want to unit test my implementation of MyMethod but I do not know how to create the correct context for CallContext with a test user.
How can I test my implementation MyMethod with a predefined user in the CallContext?
Edit:
It seems possible to create and pass an instance of CallContext by calling the constructor
public CallContext(object server, ServerCallContext context)
I can create the ServerCallContext object via TestServerCallContext.Create(), see here.
However I do not know what to pass for object server. Does anyone have an example for me?
CodePudding user response:
For unit testing gRPC with authentication and user context the following approach was my solution:
public static ProtoBuf.Grpc.CallContext TestCallContext(Guid user)
{
var serverCallContext = TestServerCallContext.Create(
method: nameof(IGrpcGreetingService.Greeting)
, host: "localhost"
, deadline: DateTime.Now.AddMinutes(30)
, requestHeaders: new Metadata()
, cancellationToken: CancellationToken.None
, peer: "10.0.0.25:5001"
, authContext: null
, contextPropagationToken: null
, writeHeadersFunc: (metadata) => Task.CompletedTask
, writeOptionsGetter: () => new WriteOptions()
, writeOptionsSetter: (writeOptions) => { }
);
var claims = new[] {
new Claim(JwtRegisteredClaimNames.Sub, "some subject"),
new Claim(JwtRegisteredClaimNames.Iat, DateTime.UtcNow.ToString()),
new Claim(JwtRegisteredClaimNames.Name, user.ToString())
};
var claimsIdentity = new ClaimsIdentity(claims);
var httpContext = new DefaultHttpContext();
httpContext.User = new ClaimsPrincipal(claimsIdentity);
serverCallContext.UserState["__HttpContext"] = httpContext;
return new ProtoBuf.Grpc.CallContext("", serverCallContext);
}
With arguments for TestServerCallContext.Create from here.
Maybe this can help somebody else save some hours or days :)
