Mocking and unit testing graphql-dotnet

552 Views Asked by At

I'm using graphql-dotnet library to query some GraphQL APIs from my C# code. Is there a way to easily mock the GraphQLHttpClient in unit tests?

2

There are 2 best solutions below

1
On BEST ANSWER

It's not easy to mock the GraphQLHttpClient directly but you can provide your own HttpClient in one of the GraphQLHttpClient constructors and mock the HttpMessageHandler. Take a look a the code below:

HttpContent content = new StringContent(_responseContent, Encoding.UTF8, "application/json");
var response = new HttpResponseMessage
{
    StatusCode = HttpStatusCode.OK,
    Content = content
};

var httpMessageHandler = new Mock<HttpMessageHandler>();
httpMessageHandler.Protected()
                  .Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
                  .ReturnsAsync(response);

HttpClient client = new HttpClient(httpMessageHandler.Object);

GraphQLHttpClient graphQlClient = new GraphQLHttpClient(GetOptions(), new NewtonsoftJsonSerializer(), client);

The above code works fine and allows me to provide any testing JSON output of the real GQL API I want in the _responseContent variable. The first line and two arguments - Encoding.UTF8, "application/json" - are quite important. Without providing the content type, the GraphQLHttpClient will throw an exception because of this line. It took me a while to find it.

I'm using Moq library for mocking objects.

0
On

The GraphQLHttpClient implements the IGraphQLWebSocketClient which extends the IGraphQLClient. The IGraphQLClient describes the following methods:

Task<GraphQLResponse<TResponse>> SendQueryAsync<TResponse>(GraphQLRequest request, CancellationToken cancellationToken = default);
        
Task<GraphQLResponse<TResponse>> SendMutationAsync<TResponse>(GraphQLRequest request, CancellationToken cancellationToken = default);

Then in your test code you can provide a moq for the IGraphQLClient. You only have to be aware that you are using Dependency Injection in combination with the provided interface.

It could be look like this here:

public class UnitTest1
{
   [Fact]
   public void Test1()
   {
      var mockedService = new Mock<IGraphQLClient>();
      mockedService
         Setup(ms => ms.SendQueryAsync<string>(It.IsAny<GraphQLRequest>(), It.IsAny<CancellationToken>()))
         .ReturnsAsync(new GraphQLResponse<string>());

         var service = new AnythingWithGraphQLDependency(mockedService.Object);

   }
}

public class AnythingWithGraphQLDependency
{
   private readonly IGraphQLClient _client;

   public AnythingWithGraphQLDependency(IGraphQLClient client)
   {
      _client = client;
   }

   public async Task<string> Test(string query, CancellationToken cancellationToken)
   {
      var response = await _client.SendQueryAsync<string>(new GraphQLRequest(query), cancellationToken);

      //Code to be tested goes here
   }
}