Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tests are added #7

Merged
merged 2 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/dotnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,6 @@ jobs:
- name: Build
run: dotnet build --no-restore
working-directory: ./Catalog/
- name: Test
run: dotnet test --no-build --verbosity normal
working-directory: ./Catalog/
2 changes: 0 additions & 2 deletions Catalog/Catalog.API/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@

var builder = WebApplication.CreateBuilder(args);

/*builder.Services.AddAutoMapper(typeof());*/

var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
Expand Down
35 changes: 35 additions & 0 deletions Catalog/Catalog.Test/Catalog.Test.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0"/>
<PackageReference Include="Moq" Version="4.20.70" />
<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="6.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<Compile Remove="UnitTest1.cs" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Catalog.API\Catalog.API.csproj" />
<ProjectReference Include="..\Catalog.Core\Catalog.Core.csproj" />
</ItemGroup>

</Project>
1 change: 1 addition & 0 deletions Catalog/Catalog.Test/GlobalUsings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
global using Xunit;
207 changes: 207 additions & 0 deletions Catalog/Catalog.Test/ProductControllerTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
using Catalog.API.Controllers;
using Catalog.Core.DTO;
using Catalog.Core.Entities;
using Catalog.Core.Repositories;
using FluentValidation;
using FluentValidation.Results;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Moq;

namespace Catalog.Test;

public class ProductControllerTests
{
private readonly Mock<IProductRepository> _productRepositoryMock;
private readonly Mock<ILogger<ProductController>> _loggerMock;
private readonly Mock<IValidator<Product>> _validatorMock;
private readonly ProductController _controller;

public ProductControllerTests()
{
_productRepositoryMock = new Mock<IProductRepository>();
_loggerMock = new Mock<ILogger<ProductController>>();
_validatorMock = new Mock<IValidator<Product>>();
_controller = new ProductController(_productRepositoryMock.Object, _loggerMock.Object, _validatorMock.Object);
}

[Fact]
public async Task Post_ValidProduct_ReturnsCreatedResult()
{
// Arrange
var productDtoRequest = new ProductDtoRequest
{
Name = "Test Product",
Description = "Test Description",
Price = 100,
Category = "Test Category",
Stock = 10,
Image = null
};

var product = new Product
{
Id = 1,
Name = productDtoRequest.Name,
Description = productDtoRequest.Description,
Price = productDtoRequest.Price,
Category = productDtoRequest.Category,
Stock = productDtoRequest.Stock
};

_validatorMock.Setup(v => v.ValidateAsync(It.IsAny<Product>(), default))
.ReturnsAsync(new ValidationResult());

_productRepositoryMock.Setup(repo => repo.CreateAsync(It.IsAny<Product>()))
.Returns(Task.CompletedTask);

// Act
var result = await _controller.Post(productDtoRequest);

// Assert
var createdResult = Assert.IsType<CreatedAtActionResult>(result.Result);
var returnValue = Assert.IsType<Product>(createdResult.Value);
Assert.Equal(product.Name, returnValue.Name);
_productRepositoryMock.Verify(repo => repo.CreateAsync(It.IsAny<Product>()), Times.Once);
}

[Fact]
public async Task Post_InvalidProduct_ReturnsBadRequest()
{
// Arrange
var productDtoRequest = new ProductDtoRequest
{
Name = "Test Product",
Description = "Test Description",
Price = 100,
Category = "Test Category",
Stock = 10,
Image = null
};

var validationFailures = new List<ValidationFailure>
{
new ValidationFailure("Name", "Name is required")
};

_validatorMock.Setup(v => v.ValidateAsync(It.IsAny<Product>(), default))
.ReturnsAsync(new ValidationResult(validationFailures));

// Act
var result = await _controller.Post(productDtoRequest);

// Assert
var badRequestResult = Assert.IsType<BadRequestObjectResult>(result.Result);
var problemDetails = Assert.IsType<ValidationProblemDetails>(badRequestResult.Value);
Assert.Contains("Name", problemDetails.Errors);
}

[Fact]
public async Task Get_ReturnsOkWithProducts()
{
// Arrange
var products = new List<Product>
{
new Product { Id = 1, Name = "Product 1" },
new Product { Id = 2, Name = "Product 2" }
};

_productRepositoryMock.Setup(repo => repo.GetAllAsync())
.ReturnsAsync(products);

// Act
var result = await _controller.Get();

// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
var returnValue = Assert.IsType<List<ProductDtoResponse>>(okResult.Value);
Assert.Equal(2, returnValue.Count);
}

[Fact]
public async Task GetProduct_ExistingId_ReturnsOk()
{
// Arrange
var product = new Product { Id = 1, Name = "Product 1" };

_productRepositoryMock.Setup(repo => repo.GetByIdAsync(1))
.ReturnsAsync(product);

// Act
var result = await _controller.GetProduct(1);

// Assert
var okResult = Assert.IsType<OkObjectResult>(result.Result);
var returnValue = Assert.IsType<ProductDtoResponse>(okResult.Value);
Assert.Equal(product.Name, returnValue.Name);
}

[Fact]
public async Task GetProduct_NonExistingId_ReturnsNotFound()
{
// Arrange
_productRepositoryMock.Setup(repo => repo.GetByIdAsync(1))
.ReturnsAsync((Product)null!);

// Act
var result = await _controller.GetProduct(1);

// Assert
Assert.IsType<NotFoundResult>(result.Result);
}

[Fact]
public async Task Put_ValidUpdate_ReturnsOk()
{
// Arrange
var product = new Product { Id = 1, Name = "Product 1", Price = 100 };
var updateDto = new ProductDtoUpdate { Name = "Updated Product", Price = 150 };

_productRepositoryMock.Setup(repo => repo.GetByIdAsync(1))
.ReturnsAsync(product);

_productRepositoryMock.Setup(repo => repo.UpdateAsync(It.IsAny<Product>()))
.Returns(Task.CompletedTask);

// Act
var result = await _controller.Put(1, updateDto);

// Assert
Assert.IsType<OkResult>(result);
_productRepositoryMock.Verify(repo => repo.UpdateAsync(It.IsAny<Product>()), Times.Once);
}

[Fact]
public async Task Delete_ExistingId_ReturnsOk()
{
// Arrange
var product = new Product { Id = 1, Name = "Product 1" };

_productRepositoryMock.Setup(repo => repo.GetByIdAsync(1))
.ReturnsAsync(product);

_productRepositoryMock.Setup(repo => repo.RemoveAsync(1))
.Returns(Task.CompletedTask);

// Act
var result = await _controller.Delete(1);

// Assert
Assert.IsType<OkResult>(result);
_productRepositoryMock.Verify(repo => repo.RemoveAsync(1), Times.Once);
}

[Fact]
public async Task Delete_NonExistingId_ReturnsNotFound()
{
// Arrange
_productRepositoryMock.Setup(repo => repo.GetByIdAsync(1))
.ReturnsAsync((Product)null!);

// Act
var result = await _controller.Delete(1);

// Assert
Assert.IsType<NotFoundResult>(result);
}
}
9 changes: 9 additions & 0 deletions Catalog/Catalog.Test/UnitTest1.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Catalog.Test;

public class UnitTest1
{
[Fact]
public void Test1()
{
}
}
6 changes: 6 additions & 0 deletions Catalog/Catalog.sln
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Catalog.Infrastructure", "C
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Catalog.Core", "Catalog.Core\Catalog.Core.csproj", "{8BB165BC-4495-4D19-848B-E4171E76E12E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Catalog.Test", "Catalog.Test\Catalog.Test.csproj", "{433F961A-EFEA-4E51-ABD5-26B03E226775}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -24,5 +26,9 @@ Global
{8BB165BC-4495-4D19-848B-E4171E76E12E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8BB165BC-4495-4D19-848B-E4171E76E12E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8BB165BC-4495-4D19-848B-E4171E76E12E}.Release|Any CPU.Build.0 = Release|Any CPU
{433F961A-EFEA-4E51-ABD5-26B03E226775}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{433F961A-EFEA-4E51-ABD5-26B03E226775}.Debug|Any CPU.Build.0 = Debug|Any CPU
{433F961A-EFEA-4E51-ABD5-26B03E226775}.Release|Any CPU.ActiveCfg = Release|Any CPU
{433F961A-EFEA-4E51-ABD5-26B03E226775}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal