Added Integration test that uses Refit

This commit is contained in:
Alex Hyett 2023-07-07 14:27:35 +01:00
parent 0cb97f48df
commit e96d78bd21
15 changed files with 124 additions and 16 deletions

View file

@ -13,9 +13,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GitHubActionsDemo.Persistan
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{015E0E24-CD73-48C7-8565-5A566F5DAB87}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GitHubActionsDemo.Api.Tests", "test\GitHubActionsDemo.Api.Tests\GitHubActionsDemo.Api.Tests.csproj", "{AA6299AC-C10C-49CD-89A3-33122123AE7A}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GitHubActionsDemo.Api.Unit.Tests", "test\GitHubActionsDemo.Api.Unit.Tests\GitHubActionsDemo.Api.Unit.Tests.csproj", "{AA6299AC-C10C-49CD-89A3-33122123AE7A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GitHubActionsDemo.Service.Tests", "test\GitHubActionsDemo.Service.Tests\GitHubActionsDemo.Service.Tests.csproj", "{957CACE1-E456-48DA-84A7-02A81B9F0371}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GitHubActionsDemo.Service.Unit.Tests", "test\GitHubActionsDemo.Service.Unit.Tests\GitHubActionsDemo.Service.Unit.Tests.csproj", "{957CACE1-E456-48DA-84A7-02A81B9F0371}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GitHubActionsDemo.Api.Integration.Tests", "test\GitHubActionsDemo.Api.Integration.Tests\GitHubActionsDemo.Api.Integration.Tests.csproj", "{F846BF32-3117-468E-8A90-6692D498BB40}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -46,6 +48,10 @@ Global
{957CACE1-E456-48DA-84A7-02A81B9F0371}.Debug|Any CPU.Build.0 = Debug|Any CPU
{957CACE1-E456-48DA-84A7-02A81B9F0371}.Release|Any CPU.ActiveCfg = Release|Any CPU
{957CACE1-E456-48DA-84A7-02A81B9F0371}.Release|Any CPU.Build.0 = Release|Any CPU
{F846BF32-3117-468E-8A90-6692D498BB40}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F846BF32-3117-468E-8A90-6692D498BB40}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F846BF32-3117-468E-8A90-6692D498BB40}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F846BF32-3117-468E-8A90-6692D498BB40}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{E3C34F79-B74E-44A4-99F0-B0B3C2D7CCB2} = {53A44CCA-C5C6-4D98-91B8-D331D68BF7B0}
@ -53,5 +59,6 @@ Global
{339301B3-E9BD-45D1-B6A9-94F41367DF16} = {53A44CCA-C5C6-4D98-91B8-D331D68BF7B0}
{AA6299AC-C10C-49CD-89A3-33122123AE7A} = {015E0E24-CD73-48C7-8565-5A566F5DAB87}
{957CACE1-E456-48DA-84A7-02A81B9F0371} = {015E0E24-CD73-48C7-8565-5A566F5DAB87}
{F846BF32-3117-468E-8A90-6692D498BB40} = {015E0E24-CD73-48C7-8565-5A566F5DAB87}
EndGlobalSection
EndGlobal

View file

@ -12,5 +12,5 @@ public interface IBookApi
Task<BookResponse> GetBookAsync(int bookId);
[Post("/books/")]
Task<IList<BookResponse>> CreateBookAsync([Body] BookRequest request);
Task<BookResponse> CreateBookAsync([Body] BookRequest request);
}

View file

@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Nullable>disable</Nullable>
</PropertyGroup>
<ItemGroup>

View file

@ -11,9 +11,7 @@ public class BookRequestValidator : AbstractValidator<BookRequest>
RuleFor(x => x.Isbn)
.NotEmpty()
.MinimumLength(10)
.MaximumLength(17)
.Matches(@"^(?:ISBN(?:-1[03])?:? )?(?=[0-9X]{10}$|(?=(?:[0-9]+[- ]){3})[- 0 - 9X]{ 13}$| 97[89][0 - 9]{ 10}$| (?= (?:[0 - 9] +[- ]){ 4})[- 0 - 9]{ 17}$)(?: 97[89][- ] ?)?[0 - 9]{ 1,5}[- ]?[0 - 9]+[- ]?[0 - 9] +[- ]?[0 - 9X]$");
.Matches(@"^(?=(?:\D*\d){10}(?:(?:\D*\d){3})?$)[\d-]+$");
RuleFor(x => x.DatePublished)
.NotEmpty();

View file

@ -63,7 +63,7 @@ public class DbContext : IDbContext
book_id INT NOT NULL AUTO_INCREMENT,
title VARCHAR(255),
author_id INT NOT NULL,
isbn VARCHAR(13) NOT NULL,
isbn VARCHAR(20) NOT NULL,
date_published DATETIME NOT NULL,
date_created DATETIME NOT NULL,
date_modified DATETIME NOT NULL,

View file

@ -1,6 +0,0 @@
namespace GitHubActionsDemo.Service.Models;
public class NotFound
{
}

View file

@ -0,0 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="Shouldly" Version="4.2.1" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.2.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\GitHubActionsDemo.Api.Sdk\GitHubActionsDemo.Api.Sdk.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,78 @@
using GitHubActionsDemo.Api.Sdk.Authors;
using GitHubActionsDemo.Api.Sdk.Books;
using Refit;
using Shouldly;
namespace GitHubActionsDemo.Api.Integration.Tests;
public class IntegrationTests
{
private const string BaseUri = "http://localhost:5275";
private readonly IAuthorApi _authorApi = RestService.For<IAuthorApi>(BaseUri);
private readonly IBookApi _bookApi = RestService.For<IBookApi>(BaseUri);
[Fact]
public async Task Given_valid_author_should_create_author()
{
var request = new AuthorRequest
{
FirstName = $"{Guid.NewGuid()}",
LastName = $"{Guid.NewGuid()}"
};
var author = await _authorApi.CreateAuthorAsync(request);
author.AuthorId.ShouldNotBe(0);
author.FirstName.ShouldBe(request.FirstName);
author.LastName.ShouldBe(request.LastName);
author.DateCreated.ShouldBeInRange(DateTime.UtcNow.AddSeconds(-5), DateTime.UtcNow.AddSeconds(5));
author.DateModified.ShouldBeInRange(DateTime.UtcNow.AddSeconds(-5), DateTime.UtcNow.AddSeconds(5));
}
[Fact]
public async Task Given_created_author_should_return_author_on_get()
{
var request = new AuthorRequest
{
FirstName = $"{Guid.NewGuid()}",
LastName = $"{Guid.NewGuid()}"
};
var createdAuthor = await _authorApi.CreateAuthorAsync(request);
var author = await _authorApi.GetAuthorAsync(createdAuthor.AuthorId);
author.AuthorId.ShouldBe(createdAuthor.AuthorId);
author.FirstName.ShouldBe(request.FirstName);
author.LastName.ShouldBe(request.LastName);
author.DateCreated.ShouldBeInRange(DateTime.UtcNow.AddSeconds(-5), DateTime.UtcNow.AddSeconds(5));
author.DateModified.ShouldBeInRange(DateTime.UtcNow.AddSeconds(-5), DateTime.UtcNow.AddSeconds(5));
}
[Fact]
public async Task Given_valid_book_should_return_book()
{
var authorRequest = new AuthorRequest
{
FirstName = $"{Guid.NewGuid()}",
LastName = $"{Guid.NewGuid()}"
};
var createdAuthor = await _authorApi.CreateAuthorAsync(authorRequest);
var bookRequest = new BookRequest
{
AuthorId = createdAuthor.AuthorId,
Title = "Once upon a time",
Isbn = "978-93-5489-3896",
DatePublished = new DateTime(2020, 01, 01)
};
var createdBook = await _bookApi.CreateBookAsync(bookRequest);
createdBook.Title.ShouldBe(bookRequest.Title);
createdBook.Isbn.ShouldBe(bookRequest.Isbn);
createdBook.Author.AuthorId.ShouldBe(createdAuthor.AuthorId);
createdBook.Author.FirstName.ShouldBe(authorRequest.FirstName);
createdBook.Author.LastName.ShouldBe(authorRequest.LastName);
}
}

View file

@ -0,0 +1 @@
global using Xunit;

View file

@ -8,7 +8,7 @@ using Microsoft.AspNetCore.Http.HttpResults;
using GitHubActionsDemo.Api.Sdk.Authors;
using GitHubActionsDemo.Api.Sdk.Shared;
namespace GitHubActionsDemo.Api.Tests;
namespace GitHubActionsDemo.Api.Unit.Tests;
public class AuthorsControllerTests
{

View file

@ -4,7 +4,7 @@ using GitHubActionsDemo.Persistance.Models;
using GitHubActionsDemo.Service.Models;
using Microsoft.Extensions.Logging;
namespace GitHubActionsDemo.Service.Tests;
namespace GitHubActionsDemo.Service.Unit.Tests;
public class LibraryServiceTests
{