Skip to content

Instantly share code, notes, and snippets.

@Elfocrash
Created July 10, 2019 10:40
Show Gist options
  • Star 20 You must be signed in to star a gist
  • Fork 12 You must be signed in to fork a gist
  • Save Elfocrash/101ffc29947832545cdaebcb259c2f44 to your computer and use it in GitHub Desktop.
Save Elfocrash/101ffc29947832545cdaebcb259c2f44 to your computer and use it in GitHub Desktop.
ASP.NET Core Integration tests code from my video: https://www.youtube.com/watch?v=7roqteWLw4s
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Tweetbook.Contracts.V1;
using Tweetbook.Contracts.V1.Requests;
using Tweetbook.Contracts.V1.Responses;
using Tweetbook.Data;
namespace Tweetbook.IntegrationTests
{
public class IntegrationTest
{
protected readonly HttpClient TestClient;
protected IntegrationTest()
{
var appFactory = new WebApplicationFactory<Startup>()
.WithWebHostBuilder(builder =>
{
builder.ConfigureServices(services =>
{
services.RemoveAll(typeof(DataContext));
services.AddDbContext<DataContext>(options => { options.UseInMemoryDatabase("TestDb"); });
});
});
TestClient = appFactory.CreateClient();
}
protected async Task AuthenticateAsync()
{
TestClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", await GetJwtAsync());
}
protected async Task<PostResponse> CreatePostAsync(CreatePostRequest request)
{
var response = await TestClient.PostAsJsonAsync(ApiRoutes.Posts.Create, request);
return await response.Content.ReadAsAsync<PostResponse>();
}
private async Task<string> GetJwtAsync()
{
var response = await TestClient.PostAsJsonAsync(ApiRoutes.Identity.Register, new UserRegistrationRequest
{
Email = "test@integration.com",
Password = "SomePass1234!"
});
var registrationResponse = await response.Content.ReadAsAsync<AuthSuccessResponse>();
return registrationResponse.Token;
}
}
}
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using FluentAssertions;
using Tweetbook.Contracts.V1;
using Tweetbook.Contracts.V1.Requests;
using Tweetbook.Domain;
using Xunit;
namespace Tweetbook.IntegrationTests
{
public class PostsControllerTests : IntegrationTest
{
[Fact]
public async Task GetAll_WithoutAnyPosts_ReturnsEmptyResponse()
{
// Arrange
await AuthenticateAsync();
// Act
var response = await TestClient.GetAsync(ApiRoutes.Posts.GetAll);
// Assert
response.StatusCode.Should().Be(HttpStatusCode.OK);
(await response.Content.ReadAsAsync<List<Post>>()).Should().BeEmpty();
}
[Fact]
public async Task Get_ReturnsPost_WhenPostExistsInTheDatabase()
{
// Arrange
await AuthenticateAsync();
var createdPost = await CreatePostAsync(new CreatePostRequest {Name = "Test post"});
// Act
var response = await TestClient.GetAsync(ApiRoutes.Posts.Get.Replace("{postId}", createdPost.Id.ToString()));
// Assert
response.StatusCode.Should().Be(HttpStatusCode.OK);
var returnedPost = await response.Content.ReadAsAsync<Post>();
returnedPost.Id.Should().Be(createdPost.Id);
returnedPost.Name.Should().Be("Test post");
}
}
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FluentAssertions" Version="5.7.0" />
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="2.2.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Tweetbook\Tweetbook.csproj" />
</ItemGroup>
</Project>
@Elfocrash
Copy link
Author

Thanks for posting this @trolit, I should have proivided this myself but I had the notifications suppressed.

@danich93
Copy link

@trolit exactly what I came here for, thanks 👍

@gichamba
Copy link

Hey 👋. The ApiRoutes is a class I created in the main project to manage the application’s uris in an elegant way. It’s manually created and it can be found in the project’s main repo under Contracts.

Where do we find the main project?

@swarooprooney
Copy link

I am trying to integration test my .NET 5 project using similar setup to what has been described in the video. The unit test run fine when I run them individually but when I run them all at once first to be executed passes and rest fail, when I debugged it was because the user already existed. I think the context is being shared among the tests but I do not know how to not share it. Any help please?

@swarooprooney
Copy link

Ok I figured it out. I had to give different database name for each run
the code is as below
var dbName = Guid.NewGuid().ToString(); var appFactory = new WebApplicationFactory<Startup>() .WithWebHostBuilder(builder => { builder.ConfigureServices(services => { var descriptor = services.SingleOrDefault(d => d.ServiceType == typeof(DbContextOptions<DataContext>)); if (descriptor != null) { services.Remove(descriptor); } services.AddDbContext<DataContext>(options => { options.UseInMemoryDatabase(dbName); }); }); }); TestClient = appFactory.CreateClient();

@jarrelpothoff
Copy link

i got a null reference error on variable response in GetJwtAsync() method. I copied the same code. I use .net core 5.0 web api. Anyone know the fix?

`private async Task GetJwtAsync()
{
var response = await TestClient.PostAsJsonAsync(ApiRoutes.Identity.Register, new UserRegistrationRequest
{
Email = "test@integration.com",
Password = "SomePass1234!"
});

            var registrationResponse = await response.Content.ReadAsAsync<AuthSuccessResponse>();
            return registrationResponse.Token;
        }`

@ivandamyanov
Copy link

Hey 👋. The ApiRoutes is a class I created in the main project to manage the application’s uris in an elegant way. It’s manually created and it can be found in the project’s main repo under Contracts.

Where do we find the main project?

I have found this repo where credits were also given to Nick: https://github.com/MohamedAshraf004/TweetbookAPI

@jsdevtom
Copy link

Hey wave. The ApiRoutes is a class I created in the main project to manage the application’s uris in an elegant way. It’s manually created and it can be found in the project’s main repo under Contracts.

Where do we find the main project?

I have found this repo where credits were also given to Nick: https://github.com/MohamedAshraf004/TweetbookAPI

This repo is no longer available

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment