A couple ways I test my .NET APIs 
Tags: csharp, testing
Published: 2021-02-26 16:16:02

Recently I have undertaken some work that required either building a whole new API or regression testing another API. 

Through that experience I used 3 techniques to help build my confidence that what I was building actually worked, these are: 

- Unit Tests 
- In Memory API Tests with `WebApplicationFactory<TEntryPoint>` 
- Newman Tests 

I will assume that everyone is familiar with unit tests in C# but just a quick note that my favourite framework is XUnit. I really enjoy the simplicity that it brings and allows me to get up and running super quickly. 

## In Memory API Tests with `WebApplicationFactory<TEntryPoint>` 

tl;dr; 

Check out this GitHub repo
 
https://github.com/GrantHair5/DotNetApiInMemoryTests 

It has some pretty nice examples at a **very** basic level I'm taking lets get some fruit from a basket kinda stuff. 

### How? 
 
The MVP of this test is `WebApplicationFactory<TEntryPoint>` it allows me to run an in-memory version of my API using `TestServer` this gives me access to a `HttpClient` and also my actual API. I can then send HTTP calls to my API as I would do in real life and assert the responses. 

This is a great time to plug one of my favourite NuGet packages, FluentAssertions. It gives you the ability to assert test cases using plain English style language and makes complex test assertions a breeze. 

Anyways, 

To use `WebApplicationFactory<TEntryPoint>`

You would write something like the following: 

```csharp
public class ApiWebApplicationFactory : WebApplicationFactory<Startup>
    {
        protected override void ConfigureWebHost(IWebHostBuilder builder)
        {
            builder.ConfigureTestServices(services =>
            {
                services.AddTransient<IFruitBasket, StubbedFruitBasket>();
            });
        }
    }
```

`ApiWebApplicationFactory` will become your new best friend.

Basically this is allowing us to override the default implementation of `IFruitBasket` with our new `StubbedFruitBasket` perfect for testing stuff with. 

Then I inherit `ApiWebApplicationFactory` into my next best friend `IntegrationTestBase` which I use across each of my integration tests to get access to that sweet sweet in memory API. 

```csharp
 public class IntegrationTestBase : IClassFixture<ApiWebApplicationFactory>
    {
        protected readonly ApiWebApplicationFactory Factory;
        protected readonly HttpClient Client;

        public IntegrationTestBase(ApiWebApplicationFactory fixture)
        {
            Factory = fixture;
            Client = Factory.CreateClient();
        }
    }
```

Then my tests look something like this: 

```csharp
 public class FruitApiShould : IntegrationTestBase
    {
        public FruitApiShould(ApiWebApplicationFactory fixture) : base(fixture)
        {
        }

        [Fact]
        public async Task Return_Two_Fruits_From_Stubbed_Basket()
        {
            var response = await Client.GetAsync("/api/Fruit/Basket");
            response.StatusCode.Should().Be(HttpStatusCode.OK);

            var basket = JsonConvert.DeserializeObject<IEnumerable<Fruit>>(await response.Content.ReadAsStringAsync());
            basket.Should().HaveCount(2);
        }
}
```

If I want to override the stubbed implementation of my `IFruitBasket` I can do this by using my `ApiWebApplicationFactory Factory` from `IntegrationTestBase` to call `Factory.WithWebHostBuilder()` like so:

```csharp
[Fact]
        public async Task Return_Four_Fruits_From_Real_Basket_Overriden_By_With_Web_Host_Builder()
        {
            // WithWebHostBuilder will allow us to override the base Client with any new services that we require.
            var client = Factory.WithWebHostBuilder(builder =>
            {
                builder.ConfigureServices(services =>
                {
                    services.AddTransient<IFruitBasket, FruitBasket>();
                });
            }).CreateClient();

            var response = await client.GetAsync("/api/Fruit/Basket");
            response.StatusCode.Should().Be(HttpStatusCode.OK);

            var basket = JsonConvert.DeserializeObject<IEnumerable<Fruit>>(await response.Content.ReadAsStringAsync());
            basket.Should().HaveCount(4);
        }
```

Simple right :+1:

## Some things to note 

1: `services.ConfigureTestServices()` is called after `services.ConfigureServices()` in the natural pipeline allowing us to override implementations or configuration or databases etc. 


2: The above is obviously not a real life implementation and should be used as a guide, any terrible code is not a reflection of my real life performance :joy: 

## Newman Tests 

I have probably already bored you to death so I'll just drop a tl;dr; here 

### tl;dr; 

Newman is an NPM package

It allows you to run many http requests from a postman collection 

You can write JavaScripty style tests against your collections, for me these were: 

Is my status code 200 

Is my JSON response what I expect it to be 

It is super cool and helpful. 

It saved me so much time as I didn't have to hit over 120 endpoints individually. 

Check out this link for more info: 

https://learning.postman.com/docs/running-collections/using-newman-cli/command-line-integration-with-newman/


Hope this was of help

See Ya :wave: