Skip to content

Commit

Permalink
Added tests for the Warehouse example's queries
Browse files Browse the repository at this point in the history
  • Loading branch information
oskardudycz committed May 15, 2021
1 parent d83bc9a commit fa065c6
Show file tree
Hide file tree
Showing 13 changed files with 382 additions and 45 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Threading.Tasks;
using Core.Testing;
using FluentAssertions;
using Microsoft.AspNetCore.Hosting;
using Warehouse.Products.GettingProductDetails;
using Warehouse.Products.GettingProducts;
using Warehouse.Products.RegisteringProduct;
using Xunit;

namespace Warehouse.Api.Tests.Products.GettingProductDetails
{
public class GetProductDetailsFixture: ApiFixture
{
protected override string ApiUrl => "/api/products";

protected override Func<IWebHostBuilder, IWebHostBuilder> SetupWebHostBuilder =>
whb => WarehouseTestWebHostBuilder.Configure(whb, nameof(GetProductDetailsFixture));

public ProductDetails ExistingProduct = default!;

public Guid ProductId = default!;

public override async Task InitializeAsync()
{
var registerProduct = new RegisterProductRequest("IN11111", "ValidName", "ValidDescription");
var registerResponse = await Post(registerProduct);

registerResponse.EnsureSuccessStatusCode()
.StatusCode.Should().Be(HttpStatusCode.Created);

ProductId = await registerResponse.GetResultFromJson<Guid>();

var (sku, name, description) = registerProduct;
ExistingProduct = new ProductDetails(ProductId, sku!, name!, description);
}
}

public class GetProductDetailsTests: IClassFixture<GetProductDetailsFixture>
{
private readonly GetProductDetailsFixture fixture;

public GetProductDetailsTests(GetProductDetailsFixture fixture)
{
this.fixture = fixture;
}

[Fact]
public async Task ValidRequest_With_NoParams_ShouldReturn_200()
{
// Given

// When
var response = await fixture.Get(fixture.ProductId.ToString());

// Then
response.EnsureSuccessStatusCode()
.StatusCode.Should().Be(HttpStatusCode.OK);

var product = await response.GetResultFromJson<ProductDetails>();
product.Should().NotBeNull();
product.Should().BeEquivalentTo(fixture.ExistingProduct);
}

[Theory]
[InlineData(12)]
[InlineData("not-a-guid")]
public async Task InvalidGuidId_ShouldReturn_400(object invalidId)
{
// Given

// When
var response = await fixture.Get($"{invalidId}");

// Then
response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
}

[Fact]
public async Task NotExistingId_ShouldReturn_404()
{
// Given
var notExistingId = Guid.NewGuid();

// When
var response = await fixture.Get($"{notExistingId}");

// Then
response.StatusCode.Should().Be(HttpStatusCode.NotFound);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Core.Testing;
using FluentAssertions;
using Microsoft.AspNetCore.Hosting;
using Warehouse.Products.GettingProducts;
using Warehouse.Products.RegisteringProduct;
using Xunit;

namespace Warehouse.Api.Tests.Products.GettingProducts
{
public class GetProductsFixture: ApiFixture
{
protected override string ApiUrl => "/api/products";

protected override Func<IWebHostBuilder, IWebHostBuilder> SetupWebHostBuilder =>
whb => WarehouseTestWebHostBuilder.Configure(whb, nameof(GetProductsFixture));

public IList<ProductListItem> RegisteredProducts = new List<ProductListItem>();

public override async Task InitializeAsync()
{
var productsToRegister = new[]
{
new RegisterProductRequest("ZX1234", "ValidName", "ValidDescription"),
new RegisterProductRequest("AD5678", "OtherValidName", "OtherValidDescription"),
new RegisterProductRequest("BH90210", "AnotherValid", "AnotherValidDescription")
};

foreach (var registerProduct in productsToRegister)
{
var registerResponse = await Post(registerProduct);
registerResponse.EnsureSuccessStatusCode()
.StatusCode.Should().Be(HttpStatusCode.Created);

var createdId = await registerResponse.GetResultFromJson<Guid>();

var (sku, name, _) = registerProduct;
RegisteredProducts.Add(new ProductListItem(createdId, sku!, name!));
}
}
}

public class GetProductsTests: IClassFixture<GetProductsFixture>
{
private readonly GetProductsFixture fixture;

public GetProductsTests(GetProductsFixture fixture)
{
this.fixture = fixture;
}

[Fact]
public async Task ValidRequest_With_NoParams_ShouldReturn_200()
{
// Given

// When
var response = await fixture.Get();

// Then
response.EnsureSuccessStatusCode()
.StatusCode.Should().Be(HttpStatusCode.OK);

var products = await response.GetResultFromJson<IReadOnlyList<ProductListItem>>();
products.Should().NotBeEmpty();
products.Should().BeEquivalentTo(fixture.RegisteredProducts);
}

[Fact]
public async Task ValidRequest_With_Filter_ShouldReturn_SubsetOfRecords()
{
// Given
var filteredRecord = fixture.RegisteredProducts.First();
var filter = fixture.RegisteredProducts.First().Sku.Substring(1);

// When
var response = await fixture.Get($"?filter={filter}");

// Then
response.EnsureSuccessStatusCode()
.StatusCode.Should().Be(HttpStatusCode.OK);

var products = await response.GetResultFromJson<IReadOnlyList<ProductListItem>>();
products.Should().NotBeEmpty();
products.Should().BeEquivalentTo(new List<ProductListItem>{filteredRecord});
}



[Fact]
public async Task ValidRequest_With_Paging_ShouldReturn_PageOfRecords()
{
// Given
const int page = 2;
const int pageSize = 1;
var filteredRecords = fixture.RegisteredProducts
.Skip(page - 1)
.Take(pageSize)
.ToList();

// When
var response = await fixture.Get($"?page={page}&pageSize={pageSize}");

// Then
response.EnsureSuccessStatusCode()
.StatusCode.Should().Be(HttpStatusCode.OK);

var products = await response.GetResultFromJson<IReadOnlyList<ProductListItem>>();
products.Should().NotBeEmpty();
products.Should().BeEquivalentTo(filteredRecords);
}

[Fact]
public async Task NegativePage_ShouldReturn_400()
{
// Given
var pageSize = -20;

// When
var response = await fixture.Get($"?page={pageSize}");

// Then
response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
}

[Theory]
[InlineData(0)]
[InlineData(-20)]
public async Task NegativeOrZeroPageSize_ShouldReturn_400(int pageSize)
{
// Given

// When
var response = await fixture.Get($"?page={pageSize}");

// Then
response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@

namespace Warehouse.Api.Tests.Products.RegisteringProduct
{
public class RegisteringProduct
public class RegisteringProductTests
{
public class RegisterProductFixture: ApiFixture
{
protected override string ApiUrl => "/api/products";

protected override Func<IWebHostBuilder, IWebHostBuilder> SetupWebHostBuilder =>
WarehouseTestWebHostBuilder.Configure;
whb => WarehouseTestWebHostBuilder.Configure(whb, nameof(RegisterProductFixture));
}

public class RegisterProductTests: IClassFixture<RegisterProductFixture>
Expand Down Expand Up @@ -78,7 +78,7 @@ public async Task RequestForExistingSKUShouldFail_ShouldReturn_409()
private static string ValidSKU => $"CC{DateTime.Now.Ticks}";
private const string ValidDescription = "VALID_DESCRIPTION";

public static TheoryData<RegisterProductRequest> ValidRequests = new ()
public static TheoryData<RegisterProductRequest> ValidRequests = new()
{
new RegisterProductRequest(ValidSKU, ValidName, ValidDescription),
new RegisterProductRequest(ValidSKU, ValidName, null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,6 @@
<ProjectReference Include="..\Warehouse\Warehouse.csproj" />
</ItemGroup>

<ItemGroup>
<Folder Include="Products\GettingProductDetails" />
<Folder Include="Products\GettingProducts" />
</ItemGroup>

<ItemGroup>
<Content Include="appsettings.Development.json">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,35 @@
using Core.WebApi.Middlewares.ExceptionHandling;
using Castle.Core.Configuration;
using Core.WebApi.Middlewares.ExceptionHandling;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Warehouse.Storage;
using IConfiguration = Microsoft.Extensions.Configuration.IConfiguration;

namespace Warehouse.Api.Tests
{
public static class WarehouseTestWebHostBuilder
{
public static IWebHostBuilder Configure(IWebHostBuilder webHostBuilder)
public static IWebHostBuilder Configure(IWebHostBuilder webHostBuilder, string schemaName)
{
webHostBuilder
.ConfigureServices(services =>
{
services.AddRouting()
.AddAuthorization()
.AddCors()
.AddWarehouseServices();
.AddWarehouseServices()
.AddTransient<DbContextOptions<WarehouseDBContext>>(s =>
{
var connectionString = s.GetRequiredService<IConfiguration>().GetConnectionString("WarehouseDB");
var options = new DbContextOptionsBuilder<WarehouseDBContext>();
options.UseNpgsql(
$"{connectionString}; searchpath = {schemaName.ToLower()}",
x => x.MigrationsHistoryTable("__EFMigrationsHistory", schemaName.ToLower()));
return options.Options;
});
})
.Configure(app =>
{
Expand Down
Loading

0 comments on commit fa065c6

Please sign in to comment.