Skip to content

Commit e9f5b11

Browse files
authored
Merge pull request #7 from babisque/catalog/feature/catalog-tests
Tests are added
2 parents c6ec521 + 6509913 commit e9f5b11

File tree

7 files changed

+261
-2
lines changed

7 files changed

+261
-2
lines changed

.github/workflows/dotnet.yml

+3
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,6 @@ jobs:
2626
- name: Build
2727
run: dotnet build --no-restore
2828
working-directory: ./Catalog/
29+
- name: Test
30+
run: dotnet test --no-build --verbosity normal
31+
working-directory: ./Catalog/

Catalog/Catalog.API/Program.cs

-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88

99
var builder = WebApplication.CreateBuilder(args);
1010

11-
/*builder.Services.AddAutoMapper(typeof());*/
12-
1311
var configuration = new ConfigurationBuilder()
1412
.AddJsonFile("appsettings.json")
1513
.Build();
+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net8.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
8+
<IsPackable>false</IsPackable>
9+
<IsTestProject>true</IsTestProject>
10+
</PropertyGroup>
11+
12+
<ItemGroup>
13+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0"/>
14+
<PackageReference Include="Moq" Version="4.20.70" />
15+
<PackageReference Include="xunit" Version="2.4.2"/>
16+
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
17+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
18+
<PrivateAssets>all</PrivateAssets>
19+
</PackageReference>
20+
<PackageReference Include="coverlet.collector" Version="6.0.0">
21+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
22+
<PrivateAssets>all</PrivateAssets>
23+
</PackageReference>
24+
</ItemGroup>
25+
26+
<ItemGroup>
27+
<Compile Remove="UnitTest1.cs" />
28+
</ItemGroup>
29+
30+
<ItemGroup>
31+
<ProjectReference Include="..\Catalog.API\Catalog.API.csproj" />
32+
<ProjectReference Include="..\Catalog.Core\Catalog.Core.csproj" />
33+
</ItemGroup>
34+
35+
</Project>

Catalog/Catalog.Test/GlobalUsings.cs

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
global using Xunit;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
using Catalog.API.Controllers;
2+
using Catalog.Core.DTO;
3+
using Catalog.Core.Entities;
4+
using Catalog.Core.Repositories;
5+
using FluentValidation;
6+
using FluentValidation.Results;
7+
using Microsoft.AspNetCore.Mvc;
8+
using Microsoft.Extensions.Logging;
9+
using Moq;
10+
11+
namespace Catalog.Test;
12+
13+
public class ProductControllerTests
14+
{
15+
private readonly Mock<IProductRepository> _productRepositoryMock;
16+
private readonly Mock<ILogger<ProductController>> _loggerMock;
17+
private readonly Mock<IValidator<Product>> _validatorMock;
18+
private readonly ProductController _controller;
19+
20+
public ProductControllerTests()
21+
{
22+
_productRepositoryMock = new Mock<IProductRepository>();
23+
_loggerMock = new Mock<ILogger<ProductController>>();
24+
_validatorMock = new Mock<IValidator<Product>>();
25+
_controller = new ProductController(_productRepositoryMock.Object, _loggerMock.Object, _validatorMock.Object);
26+
}
27+
28+
[Fact]
29+
public async Task Post_ValidProduct_ReturnsCreatedResult()
30+
{
31+
// Arrange
32+
var productDtoRequest = new ProductDtoRequest
33+
{
34+
Name = "Test Product",
35+
Description = "Test Description",
36+
Price = 100,
37+
Category = "Test Category",
38+
Stock = 10,
39+
Image = null
40+
};
41+
42+
var product = new Product
43+
{
44+
Id = 1,
45+
Name = productDtoRequest.Name,
46+
Description = productDtoRequest.Description,
47+
Price = productDtoRequest.Price,
48+
Category = productDtoRequest.Category,
49+
Stock = productDtoRequest.Stock
50+
};
51+
52+
_validatorMock.Setup(v => v.ValidateAsync(It.IsAny<Product>(), default))
53+
.ReturnsAsync(new ValidationResult());
54+
55+
_productRepositoryMock.Setup(repo => repo.CreateAsync(It.IsAny<Product>()))
56+
.Returns(Task.CompletedTask);
57+
58+
// Act
59+
var result = await _controller.Post(productDtoRequest);
60+
61+
// Assert
62+
var createdResult = Assert.IsType<CreatedAtActionResult>(result.Result);
63+
var returnValue = Assert.IsType<Product>(createdResult.Value);
64+
Assert.Equal(product.Name, returnValue.Name);
65+
_productRepositoryMock.Verify(repo => repo.CreateAsync(It.IsAny<Product>()), Times.Once);
66+
}
67+
68+
[Fact]
69+
public async Task Post_InvalidProduct_ReturnsBadRequest()
70+
{
71+
// Arrange
72+
var productDtoRequest = new ProductDtoRequest
73+
{
74+
Name = "Test Product",
75+
Description = "Test Description",
76+
Price = 100,
77+
Category = "Test Category",
78+
Stock = 10,
79+
Image = null
80+
};
81+
82+
var validationFailures = new List<ValidationFailure>
83+
{
84+
new ValidationFailure("Name", "Name is required")
85+
};
86+
87+
_validatorMock.Setup(v => v.ValidateAsync(It.IsAny<Product>(), default))
88+
.ReturnsAsync(new ValidationResult(validationFailures));
89+
90+
// Act
91+
var result = await _controller.Post(productDtoRequest);
92+
93+
// Assert
94+
var badRequestResult = Assert.IsType<BadRequestObjectResult>(result.Result);
95+
var problemDetails = Assert.IsType<ValidationProblemDetails>(badRequestResult.Value);
96+
Assert.Contains("Name", problemDetails.Errors);
97+
}
98+
99+
[Fact]
100+
public async Task Get_ReturnsOkWithProducts()
101+
{
102+
// Arrange
103+
var products = new List<Product>
104+
{
105+
new Product { Id = 1, Name = "Product 1" },
106+
new Product { Id = 2, Name = "Product 2" }
107+
};
108+
109+
_productRepositoryMock.Setup(repo => repo.GetAllAsync())
110+
.ReturnsAsync(products);
111+
112+
// Act
113+
var result = await _controller.Get();
114+
115+
// Assert
116+
var okResult = Assert.IsType<OkObjectResult>(result);
117+
var returnValue = Assert.IsType<List<ProductDtoResponse>>(okResult.Value);
118+
Assert.Equal(2, returnValue.Count);
119+
}
120+
121+
[Fact]
122+
public async Task GetProduct_ExistingId_ReturnsOk()
123+
{
124+
// Arrange
125+
var product = new Product { Id = 1, Name = "Product 1" };
126+
127+
_productRepositoryMock.Setup(repo => repo.GetByIdAsync(1))
128+
.ReturnsAsync(product);
129+
130+
// Act
131+
var result = await _controller.GetProduct(1);
132+
133+
// Assert
134+
var okResult = Assert.IsType<OkObjectResult>(result.Result);
135+
var returnValue = Assert.IsType<ProductDtoResponse>(okResult.Value);
136+
Assert.Equal(product.Name, returnValue.Name);
137+
}
138+
139+
[Fact]
140+
public async Task GetProduct_NonExistingId_ReturnsNotFound()
141+
{
142+
// Arrange
143+
_productRepositoryMock.Setup(repo => repo.GetByIdAsync(1))
144+
.ReturnsAsync((Product)null!);
145+
146+
// Act
147+
var result = await _controller.GetProduct(1);
148+
149+
// Assert
150+
Assert.IsType<NotFoundResult>(result.Result);
151+
}
152+
153+
[Fact]
154+
public async Task Put_ValidUpdate_ReturnsOk()
155+
{
156+
// Arrange
157+
var product = new Product { Id = 1, Name = "Product 1", Price = 100 };
158+
var updateDto = new ProductDtoUpdate { Name = "Updated Product", Price = 150 };
159+
160+
_productRepositoryMock.Setup(repo => repo.GetByIdAsync(1))
161+
.ReturnsAsync(product);
162+
163+
_productRepositoryMock.Setup(repo => repo.UpdateAsync(It.IsAny<Product>()))
164+
.Returns(Task.CompletedTask);
165+
166+
// Act
167+
var result = await _controller.Put(1, updateDto);
168+
169+
// Assert
170+
Assert.IsType<OkResult>(result);
171+
_productRepositoryMock.Verify(repo => repo.UpdateAsync(It.IsAny<Product>()), Times.Once);
172+
}
173+
174+
[Fact]
175+
public async Task Delete_ExistingId_ReturnsOk()
176+
{
177+
// Arrange
178+
var product = new Product { Id = 1, Name = "Product 1" };
179+
180+
_productRepositoryMock.Setup(repo => repo.GetByIdAsync(1))
181+
.ReturnsAsync(product);
182+
183+
_productRepositoryMock.Setup(repo => repo.RemoveAsync(1))
184+
.Returns(Task.CompletedTask);
185+
186+
// Act
187+
var result = await _controller.Delete(1);
188+
189+
// Assert
190+
Assert.IsType<OkResult>(result);
191+
_productRepositoryMock.Verify(repo => repo.RemoveAsync(1), Times.Once);
192+
}
193+
194+
[Fact]
195+
public async Task Delete_NonExistingId_ReturnsNotFound()
196+
{
197+
// Arrange
198+
_productRepositoryMock.Setup(repo => repo.GetByIdAsync(1))
199+
.ReturnsAsync((Product)null!);
200+
201+
// Act
202+
var result = await _controller.Delete(1);
203+
204+
// Assert
205+
Assert.IsType<NotFoundResult>(result);
206+
}
207+
}

Catalog/Catalog.Test/UnitTest1.cs

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace Catalog.Test;
2+
3+
public class UnitTest1
4+
{
5+
[Fact]
6+
public void Test1()
7+
{
8+
}
9+
}

Catalog/Catalog.sln

+6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Catalog.Infrastructure", "C
66
EndProject
77
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Catalog.Core", "Catalog.Core\Catalog.Core.csproj", "{8BB165BC-4495-4D19-848B-E4171E76E12E}"
88
EndProject
9+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Catalog.Test", "Catalog.Test\Catalog.Test.csproj", "{433F961A-EFEA-4E51-ABD5-26B03E226775}"
10+
EndProject
911
Global
1012
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1113
Debug|Any CPU = Debug|Any CPU
@@ -24,5 +26,9 @@ Global
2426
{8BB165BC-4495-4D19-848B-E4171E76E12E}.Debug|Any CPU.Build.0 = Debug|Any CPU
2527
{8BB165BC-4495-4D19-848B-E4171E76E12E}.Release|Any CPU.ActiveCfg = Release|Any CPU
2628
{8BB165BC-4495-4D19-848B-E4171E76E12E}.Release|Any CPU.Build.0 = Release|Any CPU
29+
{433F961A-EFEA-4E51-ABD5-26B03E226775}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
30+
{433F961A-EFEA-4E51-ABD5-26B03E226775}.Debug|Any CPU.Build.0 = Debug|Any CPU
31+
{433F961A-EFEA-4E51-ABD5-26B03E226775}.Release|Any CPU.ActiveCfg = Release|Any CPU
32+
{433F961A-EFEA-4E51-ABD5-26B03E226775}.Release|Any CPU.Build.0 = Release|Any CPU
2733
EndGlobalSection
2834
EndGlobal

0 commit comments

Comments
 (0)