GraphQL.NET with ASP.NET Integration Tests
Tags: dotnet, graphql, testing
Published: 2021-05-30 13:02:43

Supporting code available on [GitHub](https://github.com/mattjhosking/graphql-dotnet-execution-strategy).

# ASP.NET Integration Tests
Microsoft have created a [really effective way to perform unit tests](https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-5.0) against the closest thing to a server hosting your deployed code. Don't let the name throw you, though - these tests integrate your code modules together for testing, but aren't integrated to external resources (such as database, APIs or other services). This means that some level of mocking will still be required, but with the benefit that your entire solution (start up process, API end points, serialization, etc.) will be included in the test. It's certainly not as granular as a unit test would normally be, and I'd highly recommend those for testing complex logic, but it's a very useful tool for a higher layer of tests.

# Setting Up the Test Server
The simplest way to get running is to use the [WebApplicationFactory class](https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-5.0#basic-tests-with-the-default-webapplicationfactory) and set it up as an [xUnit class fixture](https://xunit.net/docs/shared-context). This gives you a class like this:
```csharp
public class GraphQLTests : IClassFixture<WebApplicationFactory<Startup>>
{
  private readonly WebApplicationFactory<Startup> _factory;

  public GraphQLTests(WebApplicationFactory<Startup> factory)
  {
    _factory = factory;
  }

  ...
}
```
Where `Startup` is the existing class you use in your main program. From there, you can simply call `_factory.CreateClient` to give you your HttpClient for testing.

# Mocking Dependencies
It's fairly simple to mock interfaces for your services dependent on external APIs and the like, but ideally you would mock only the communication layer and leave all the other service business logic in the test. For Entity Framework, this has an [in-memory database provider](https://docs.microsoft.com/en-us/ef/core/testing/in-memory) which is brilliant for this sort of thing. You can seed data up front (in your Arrange phase), let your code perform modifications (in the Act phase) and then verify everything is how you expect it to be (in the Assert phase). So how do you modify your service set up without having to create a new Startup class or have a whole lot of virtuals and overrides in a test class? The `WebApplicationFactory` class provides the following method to do exactly that:
```csharp
var factory = _factory.WithWebHostBuilder(builder =>
{
  builder.ConfigureServices(services =>
  {
    services.Replace(ServiceDescriptor.Singleton<IDocumentExecuter, OptimisedDocumentExecuter>());
  });
});
```
This creates a new factory that applies the additional configuration (in this case, additional service configuration).

# Executing GraphQL Queries
The integration test server allows you to create a HttpClient that has a special HttpMessageHandler that, rather than using TCP sockets, communicates directly with the in-memory server. All the usual serialisation still occurs. We can very easily use this to execute a GraphQL query, manually forming a HttpRequestMessage, but to make things a little easier, we can use GraphQL.NET's [GraphQL.Client](https://github.com/graphql-dotnet/graphql-client) package. With this in play, we can create a simple test using the HttpClient we created earlier:
```csharp
var graphClient = new GraphQLHttpClient(new GraphQLHttpClientOptions { EndPoint = new Uri("http://localhost/api/graphql") }, new SystemTextJsonSerializer(), httpClient);

var response = await graphClient
  .SendQueryAsync(@"query TestQuery($id: String!) {
  droid(id: $id) {
    id
    name
  }
}",
  new
  {
      id = "3"
  }, "TestQuery", () => new { droid = new DroidResponse() });

response.Errors.Should().BeNullOrEmpty();
response.Data.droid.Name.Should().Be("R2-D2");
```
I highly recommend you read the [GraphQL.Client docs](https://github.com/graphql-dotnet/graphql-client), but the short of it is that you provide the query, variables and operation name (fairly straight-forward), with a final parameter that specifies the "shape" of the the response. This shape provides the structure to use when deserializing the response. Finally I'm using Fluent Assertions to validate some properties of the response.