Skip to content

Commit 05737b0

Browse files
committed
Making some changes to implement Functional Tests
1 parent 6d434ad commit 05737b0

File tree

13 files changed

+136
-44
lines changed

13 files changed

+136
-44
lines changed

StoreCleanArchitecture.sln

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Store.WebApi", "src\Store.W
1313
EndProject
1414
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{A6E8ECBB-EE1B-4FD8-B53A-877A64A02EBD}"
1515
EndProject
16-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Store.UnitTests", "tests\Store.UnitTests\Store.UnitTests.csproj", "{F6FA0C39-7C4F-4511-90D5-507D23D90044}"
16+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Store.UnitTests", "tests\Store.UnitTests\Store.UnitTests.csproj", "{F6FA0C39-7C4F-4511-90D5-507D23D90044}"
1717
EndProject
18-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Store.IntegrationTests", "tests\Store.IntegrationTests\Store.IntegrationTests.csproj", "{DA1BC996-BAB4-4FD9-A94A-E38B6181E17A}"
18+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Store.IntegrationTests", "tests\Store.IntegrationTests\Store.IntegrationTests.csproj", "{DA1BC996-BAB4-4FD9-A94A-E38B6181E17A}"
19+
EndProject
20+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Store.SharedDatabaseSetup", "tests\Store.SharedDatabaseSetup\Store.SharedDatabaseSetup.csproj", "{3C31AD80-0F8C-4C04-B7B3-48CE53D7E508}"
1921
EndProject
2022
Global
2123
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -43,6 +45,10 @@ Global
4345
{DA1BC996-BAB4-4FD9-A94A-E38B6181E17A}.Debug|Any CPU.Build.0 = Debug|Any CPU
4446
{DA1BC996-BAB4-4FD9-A94A-E38B6181E17A}.Release|Any CPU.ActiveCfg = Release|Any CPU
4547
{DA1BC996-BAB4-4FD9-A94A-E38B6181E17A}.Release|Any CPU.Build.0 = Release|Any CPU
48+
{3C31AD80-0F8C-4C04-B7B3-48CE53D7E508}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
49+
{3C31AD80-0F8C-4C04-B7B3-48CE53D7E508}.Debug|Any CPU.Build.0 = Debug|Any CPU
50+
{3C31AD80-0F8C-4C04-B7B3-48CE53D7E508}.Release|Any CPU.ActiveCfg = Release|Any CPU
51+
{3C31AD80-0F8C-4C04-B7B3-48CE53D7E508}.Release|Any CPU.Build.0 = Release|Any CPU
4652
EndGlobalSection
4753
GlobalSection(SolutionProperties) = preSolution
4854
HideSolutionNode = FALSE
@@ -53,6 +59,7 @@ Global
5359
{FA30AF1B-7F01-4B93-83B6-D55852259B52} = {A98E282B-3323-452D-AB43-6D5A4346924D}
5460
{F6FA0C39-7C4F-4511-90D5-507D23D90044} = {A6E8ECBB-EE1B-4FD8-B53A-877A64A02EBD}
5561
{DA1BC996-BAB4-4FD9-A94A-E38B6181E17A} = {A6E8ECBB-EE1B-4FD8-B53A-877A64A02EBD}
62+
{3C31AD80-0F8C-4C04-B7B3-48CE53D7E508} = {A6E8ECBB-EE1B-4FD8-B53A-877A64A02EBD}
5663
EndGlobalSection
5764
GlobalSection(ExtensibilityGlobals) = postSolution
5865
SolutionGuid = {A6F246E7-577E-42ED-9C0E-8418EDD64F77}

src/Store.ApplicationCore/DTOs/Product.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,12 @@ public class ProductResponse
2828
{
2929
public int Id { get; set; }
3030
public string Name { get; set; }
31-
public string Description { get; set; }
3231
public int Stock { get; set; }
3332
public double Price { get; set; }
3433
}
34+
35+
public class SingleProductResponse : ProductResponse
36+
{
37+
public string Description { get; set; }
38+
}
3539
}

src/Store.ApplicationCore/Interfaces/IProductRepository.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ public interface IProductRepository
77
{
88
List<ProductResponse> GetProducts();
99

10-
ProductResponse GetProductById(int productId);
10+
SingleProductResponse GetProductById(int productId);
1111

1212
void DeleteProductById(int productId);
1313

14-
ProductResponse CreateProduct(CreateProductRequest request);
14+
SingleProductResponse CreateProduct(CreateProductRequest request);
1515

16-
ProductResponse UpdateProduct(int productId, UpdateProductRequest request);
16+
SingleProductResponse UpdateProduct(int productId, UpdateProductRequest request);
1717
}
1818
}

src/Store.ApplicationCore/Mappings/GeneralProfile.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public GeneralProfile()
2727
);
2828

2929
CreateMap<Product, ProductResponse>();
30+
CreateMap<Product, SingleProductResponse>();
3031
}
3132
}
3233
}

src/Store.Infrastructure/Persistence/Repositories/ProductRepository.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public ProductRepository(StoreContext storeContext, IMapper mapper)
2121
this.mapper = mapper;
2222
}
2323

24-
public ProductResponse CreateProduct(CreateProductRequest request)
24+
public SingleProductResponse CreateProduct(CreateProductRequest request)
2525
{
2626
var product = this.mapper.Map<Product>(request);
2727
product.Stock = 0;
@@ -30,7 +30,7 @@ public ProductResponse CreateProduct(CreateProductRequest request)
3030
this.storeContext.Products.Add(product);
3131
this.storeContext.SaveChanges();
3232

33-
return this.mapper.Map<ProductResponse>(product);
33+
return this.mapper.Map<SingleProductResponse>(product);
3434
}
3535

3636
public void DeleteProductById(int productId)
@@ -47,12 +47,12 @@ public void DeleteProductById(int productId)
4747
}
4848
}
4949

50-
public ProductResponse GetProductById(int productId)
50+
public SingleProductResponse GetProductById(int productId)
5151
{
5252
var product = this.storeContext.Products.Find(productId);
5353
if (product != null)
5454
{
55-
return this.mapper.Map<ProductResponse>(product);
55+
return this.mapper.Map<SingleProductResponse>(product);
5656
}
5757

5858
throw new NotFoundException();
@@ -63,7 +63,7 @@ public List<ProductResponse> GetProducts()
6363
return this.storeContext.Products.Select(p => this.mapper.Map<ProductResponse>(p)).ToList();
6464
}
6565

66-
public ProductResponse UpdateProduct(int productId, UpdateProductRequest request)
66+
public SingleProductResponse UpdateProduct(int productId, UpdateProductRequest request)
6767
{
6868
var product = this.storeContext.Products.Find(productId);
6969
if (product != null)
@@ -77,7 +77,7 @@ public ProductResponse UpdateProduct(int productId, UpdateProductRequest request
7777
this.storeContext.Products.Update(product);
7878
this.storeContext.SaveChanges();
7979

80-
return this.mapper.Map<ProductResponse>(product);
80+
return this.mapper.Map<SingleProductResponse>(product);
8181
}
8282

8383
throw new NotFoundException();

src/Store.WebApi/Controllers/ProductsController.cs

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
1-
using Microsoft.AspNetCore.Mvc;
1+
using Microsoft.AspNetCore.Http;
2+
using Microsoft.AspNetCore.Mvc;
23
using Store.ApplicationCore.DTOs;
34
using Store.ApplicationCore.Exceptions;
45
using Store.ApplicationCore.Interfaces;
56
using System.Collections.Generic;
7+
using System.Net.Mime;
68

79
namespace Store.WebApi.Controllers
810
{
911
[Route("api/[controller]")]
1012
[ApiController]
13+
[Consumes(MediaTypeNames.Application.Json)]
14+
[Produces("application/json")]
1115
public class ProductsController : Controller
1216
{
1317
private readonly IProductRepository productRepository;
@@ -17,13 +21,26 @@ public ProductsController(IProductRepository productRepository)
1721
this.productRepository = productRepository;
1822
}
1923

24+
/// <summary>
25+
/// Get all products
26+
/// </summary>
27+
/// <response code="200">Returns the products</response>
2028
[HttpGet]
21-
public ActionResult<List<ProductResponse>> GetProducts()
29+
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(List<ProductResponse>))]
30+
public ActionResult GetProducts()
2231
{
2332
return Ok(this.productRepository.GetProducts());
2433
}
2534

35+
/// <summary>
36+
/// Get a product by id
37+
/// </summary>
38+
/// <param name="id">Product id</param>
39+
/// <response code="200">Returns the existing product</response>
40+
/// <response code="404">If the product doesn't exist</response>
2641
[HttpGet("{id}")]
42+
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(SingleProductResponse))]
43+
[ProducesResponseType(StatusCodes.Status404NotFound)]
2744
public ActionResult GetProductById(int id)
2845
{
2946
try
@@ -37,14 +54,33 @@ public ActionResult GetProductById(int id)
3754
}
3855
}
3956

57+
/// <summary>
58+
/// Create a product
59+
/// </summary>
60+
/// <param name="request">Product data</param>
61+
/// <response code="201">Returns the created product</response>
62+
/// <response code="400">If the data doesn't pass the validations</response>
4063
[HttpPost]
64+
[ProducesResponseType(StatusCodes.Status201Created, Type = typeof(SingleProductResponse))]
65+
[ProducesResponseType(StatusCodes.Status400BadRequest)]
4166
public ActionResult Create(CreateProductRequest request)
4267
{
4368
var product = this.productRepository.CreateProduct(request);
44-
return Ok(product);
69+
return StatusCode(201, product);
4570
}
4671

72+
/// <summary>
73+
/// Update a product by id
74+
/// </summary>
75+
/// <param name="id">Product id</param>
76+
/// <param name="request">Product data</param>
77+
/// <response code="200">Returns the updated product</response>
78+
/// <response code="400">If the data doesn't pass the validations</response>
79+
/// <response code="404">If the product doesn't exist</response>
4780
[HttpPut("{id}")]
81+
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(SingleProductResponse))]
82+
[ProducesResponseType(StatusCodes.Status400BadRequest)]
83+
[ProducesResponseType(StatusCodes.Status404NotFound)]
4884
public ActionResult Update(int id, UpdateProductRequest request)
4985
{
5086
try
@@ -58,7 +94,15 @@ public ActionResult Update(int id, UpdateProductRequest request)
5894
}
5995
}
6096

97+
/// <summary>
98+
/// Delete a product by id
99+
/// </summary>
100+
/// <param name="id">Product id</param>
101+
/// <response code="204">If the product was deleted</response>
102+
/// <response code="404">If the product doesn't exist</response>
61103
[HttpDelete("{id}")]
104+
[ProducesResponseType(StatusCodes.Status204NoContent)]
105+
[ProducesResponseType(StatusCodes.Status404NotFound)]
62106
public ActionResult Delete(int id)
63107
{
64108
try

src/Store.WebApi/Program.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
using Microsoft.Extensions.Hosting;
44
using Store.ApplicationCore;
55
using Store.Infrastructure;
6+
using System;
7+
using System.IO;
8+
using System.Reflection;
69

710
var builder = WebApplication.CreateBuilder(args);
811

@@ -13,7 +16,11 @@
1316
builder.Services.AddControllers();
1417
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
1518
builder.Services.AddEndpointsApiExplorer();
16-
builder.Services.AddSwaggerGen();
19+
builder.Services.AddSwaggerGen(options =>
20+
{
21+
var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
22+
options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename));
23+
});
1724

1825
var app = builder.Build();
1926

src/Store.WebApi/Store.WebApi.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
<PropertyGroup>
44
<TargetFramework>net6.0</TargetFramework>
55
<ImplicitUsings>disable</ImplicitUsings>
6+
<GenerateDocumentationFile>true</GenerateDocumentationFile>
7+
<NoWarn>$(NoWarn);1591</NoWarn>
68
</PropertyGroup>
79

810
<ItemGroup>

tests/Store.IntegrationTests/SharedDatabaseFixture.cs

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
using Bogus;
2-
using Microsoft.Data.Sqlite;
1+
using Microsoft.Data.Sqlite;
32
using Microsoft.EntityFrameworkCore;
4-
using Store.ApplicationCore.Entities;
5-
using Store.ApplicationCore.Utils;
63
using Store.Infrastructure.Persistence.Contexts;
4+
using Store.SharedDatabaseSetup;
75
using System;
86
using System.Data.Common;
97

@@ -14,7 +12,7 @@ public class SharedDatabaseFixture : IDisposable
1412
private static readonly object _lock = new object();
1513
private static bool _databaseInitialized;
1614

17-
private string dbName = "TestDatabase.db";
15+
private string dbName = "IntegrationTestsDatabase.db";
1816

1917
public SharedDatabaseFixture()
2018
{
@@ -50,33 +48,14 @@ private void Seed()
5048
context.Database.EnsureDeleted();
5149
context.Database.EnsureCreated();
5250

53-
SeedData(context);
51+
DatabaseSetup.SeedData(context);
5452
}
5553

5654
_databaseInitialized = true;
5755
}
5856
}
5957
}
6058

61-
private void SeedData(StoreContext context)
62-
{
63-
var productIds = 1;
64-
var fakeProducts = new Faker<Product>()
65-
.RuleFor(o => o.Name, f => $"Product {productIds}")
66-
.RuleFor(o => o.Description, f => $"Description {productIds}")
67-
.RuleFor(o => o.Id, f => productIds++)
68-
.RuleFor(o => o.Stock, f => f.Random.Number(1, 50))
69-
.RuleFor(o => o.Price, f => f.Random.Double(0.01, 100))
70-
.RuleFor(o => o.CreatedAt, f => DateUtil.GetCurrentDate())
71-
.RuleFor(o => o.UpdatedAt, f => DateUtil.GetCurrentDate());
72-
73-
var products = fakeProducts.Generate(10);
74-
75-
context.AddRange(products);
76-
77-
context.SaveChanges();
78-
}
79-
8059
public void Dispose() => Connection.Dispose();
8160
}
8261
}

tests/Store.IntegrationTests/Store.IntegrationTests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
</PropertyGroup>
99

1010
<ItemGroup>
11-
<PackageReference Include="Bogus" Version="34.0.1" />
1211
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.1" />
1312
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
1413
<PackageReference Include="xunit" Version="2.4.1" />
@@ -24,6 +23,7 @@
2423

2524
<ItemGroup>
2625
<ProjectReference Include="..\..\src\Store.Infrastructure\Store.Infrastructure.csproj" />
26+
<ProjectReference Include="..\Store.SharedDatabaseSetup\Store.SharedDatabaseSetup.csproj" />
2727
</ItemGroup>
2828

2929
</Project>

0 commit comments

Comments
 (0)