-
-
Notifications
You must be signed in to change notification settings - Fork 522
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added example of basic CQRS using Endpoints, Nullable Reference Types…
…, Records and other C# 8-9 goodies Added tests for Registering the Product Added tests for the Warehouse example's queries Updated project and test configuration to run migrations automatically
- Loading branch information
1 parent
8881f95
commit 9c348dc
Showing
40 changed files
with
1,602 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
92 changes: 92 additions & 0 deletions
92
...le/Warehouse/Warehouse.Api.Tests/Products/GettingProductDetails/GetProductDetailsTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
using System; | ||
using System.Net; | ||
using System.Threading.Tasks; | ||
using Core.Testing; | ||
using FluentAssertions; | ||
using Microsoft.AspNetCore.Hosting; | ||
using Warehouse.Products.GettingProductDetails; | ||
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); | ||
} | ||
} | ||
} |
144 changes: 144 additions & 0 deletions
144
Sample/Warehouse/Warehouse.Api.Tests/Products/GettingProducts/GetProductsTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} | ||
} |
Oops, something went wrong.