Skip to content

Commit

Permalink
feat(unittests): added all the remaining tests for Expenses and pendi…
Browse files Browse the repository at this point in the history
…ng GetAllCategoriesQuery tests; used MockQueryable.Moq library to handle IAsyncQueriableProvider implementation
  • Loading branch information
mezdelex committed Nov 12, 2024
1 parent 478f068 commit 182e127
Show file tree
Hide file tree
Showing 16 changed files with 381 additions and 37 deletions.
4 changes: 2 additions & 2 deletions src/Domain/Entities/Category.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ namespace Domain.Entities;

public class Category : BaseEntity
{
public string Name { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
public virtual string Name { get; set; } = string.Empty;
public virtual string Description { get; set; } = string.Empty;

public virtual List<Expense> Expenses { get; set; } = default!;
}
8 changes: 4 additions & 4 deletions src/Domain/Entities/Expense.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ namespace Domain.Entities;

public class Expense : BaseEntity
{
public string Name { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
public double Value { get; set; }
public Guid CategoryId { get; set; }
public virtual string Name { get; set; } = string.Empty;
public virtual string Description { get; set; } = string.Empty;
public virtual double Value { get; set; }
public virtual Guid CategoryId { get; set; }

public virtual Category Category { get; set; } = default!;
}
6 changes: 4 additions & 2 deletions src/Infrastructure/Extensions/InfrastructureExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ IConfiguration configuration
)
{
services.AddDbContext<ApplicationDbContext>(options =>
{
options.UseLazyLoadingProxies();
options.UseSqlServer(
$"Server=sqlserver;Database={configuration["DATABASE"]};User Id=sa;Password={configuration["PASSWORD"]};TrustServerCertificate=True"
)
);
);
});
services.AddScoped<IApplicationDbContext>(provider =>
provider.GetRequiredService<ApplicationDbContext>()
);
Expand Down
3 changes: 2 additions & 1 deletion src/Infrastructure/Infrastructure.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
<PackageReference Include="masstransit" Version="8.2.3" />
<PackageReference Include="masstransit.rabbitmq" Version="8.2.3" />
<PackageReference Include="microsoft.aspnetcore.openapi" Version="8.0.7" />
<PackageReference Include="microsoft.entityframeworkcore" Version="8.0.7" />
<PackageReference Include="microsoft.entityframeworkcore" Version="9.0.0" />
<PackageReference Include="microsoft.entityframeworkcore.proxies" Version="9.0.0" />
<PackageReference Include="microsoft.entityframeworkcore.sqlserver" Version="8.0.7" />
<PackageReference Include="microsoft.entityframeworkcore.tools" Version="8.0.7">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand Down
2 changes: 1 addition & 1 deletion src/WebApi/WebApi.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.7" />
<PackageReference Include="microsoft.entityframeworkcore" Version="8.0.7" />
<PackageReference Include="microsoft.entityframeworkcore" Version="9.0.0" />
<PackageReference Include="microsoft.entityframeworkcore.design" Version="8.0.7">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ public async Task DeleteCategoryCommandHandler_ShouldDeleteCategory()
await _handler.Handle(deleteCategoryCommand, _cancellationToken);

// Assert
_repository.Verify();
_uow.Verify();
_repository.Verify(
mock => mock.DeleteAsync(It.IsAny<Guid>(), _cancellationToken),
Times.Once
);
_uow.Verify(mock => mock.SaveChangesAsync(_cancellationToken), Times.Once);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
namespace Application.UnitTests.Expenses.PostAsync;

public sealed class DeleteExpenseCommandHandlerTests
{
private readonly CancellationToken _cancellationToken;
private readonly Mock<IExpensesRepository> _repository;
private readonly Mock<IUnitOfWork> _uow;
private readonly DeleteExpenseCommandHandler _handler;

public DeleteExpenseCommandHandlerTests()
{
_cancellationToken = new();
_repository = new();
_uow = new();

_handler = new DeleteExpenseCommandHandler(_repository.Object, _uow.Object);
}

[Fact]
public async Task DeleteExpenseCommandHandler_ShouldDeleteExpense()
{
// Arrange
var deleteExpenseCommand = new DeleteExpenseCommand(Guid.NewGuid());
_repository
.Setup(mock => mock.DeleteAsync(It.IsAny<Guid>(), _cancellationToken))
.Verifiable();
_uow.Setup(mock => mock.SaveChangesAsync(_cancellationToken)).Verifiable();

// Act
await _handler.Handle(deleteExpenseCommand, _cancellationToken);

// Assert
_repository.Verify(
mock => mock.DeleteAsync(It.IsAny<Guid>(), _cancellationToken),
Times.Once
);
_uow.Verify(mock => mock.SaveChangesAsync(_cancellationToken), Times.Once);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public async Task PatchCategoryCommandHandler_ShouldPatchCategoryAndPublishEvent
"Category 1 description"
);
_validator
.Setup(mock => mock.ValidateAsync(patchCategoryCommand, _cancellationToken))
.Setup(mock => mock.ValidateAsync(It.IsAny<PatchCategoryCommand>(), _cancellationToken))
.ReturnsAsync(new ValidationResult())
.Verifiable();
_repository
Expand All @@ -50,9 +50,18 @@ public async Task PatchCategoryCommandHandler_ShouldPatchCategoryAndPublishEvent
await _handler.Handle(patchCategoryCommand, _cancellationToken);

// Assert
_validator.Verify();
_repository.Verify();
_uow.Verify();
_eventBus.Verify();
_validator.Verify(
mock => mock.ValidateAsync(It.IsAny<PatchCategoryCommand>(), _cancellationToken),
Times.Once
);
_repository.Verify(
mock => mock.PatchAsync(It.IsAny<Category>(), _cancellationToken),
Times.Once
);
_uow.Verify(mock => mock.SaveChangesAsync(_cancellationToken), Times.Once);
_eventBus.Verify(
mock => mock.PublishAsync(It.IsAny<PatchedCategoryEvent>(), _cancellationToken),
Times.Once
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
namespace Application.UnitTests.Expenses.PostAsync;

public sealed class PatchExpenseCommandHandlerTests
{
private readonly CancellationToken _cancellationToken;
private readonly Mock<IValidator<PatchExpenseCommand>> _validator;
private readonly Mock<IExpensesRepository> _repository;
private readonly Mock<IUnitOfWork> _uow;
private readonly Mock<IEventBus> _eventBus;
private readonly PatchExpenseCommandHandler _handler;

public PatchExpenseCommandHandlerTests()
{
_cancellationToken = new();
_validator = new();
_repository = new();
_uow = new();
_eventBus = new();

_handler = new PatchExpenseCommandHandler(
_validator.Object,
_repository.Object,
_uow.Object,
_eventBus.Object
);
}

[Fact]
public async Task PatchExpenseCommandHandler_ShouldPatchExpenseAndPublishEventAsync()
{
// Arrange
var patchExpenseCommand = new PatchExpenseCommand(
Guid.NewGuid(),
"Expense 1 name",
"Expense 1 description",
1,
new Guid()
);
_validator
.Setup(mock => mock.ValidateAsync(It.IsAny<PatchExpenseCommand>(), _cancellationToken))
.ReturnsAsync(new ValidationResult())
.Verifiable();
_repository
.Setup(mock => mock.PatchAsync(It.IsAny<Expense>(), _cancellationToken))
.Verifiable();
_uow.Setup(mock => mock.SaveChangesAsync(_cancellationToken)).Verifiable();
_eventBus
.Setup(mock => mock.PublishAsync(It.IsAny<PatchedExpenseEvent>(), _cancellationToken))
.Verifiable();

// Act
await _handler.Handle(patchExpenseCommand, _cancellationToken);

// Assert
_validator.Verify(
mock => mock.ValidateAsync(It.IsAny<PatchExpenseCommand>(), _cancellationToken),
Times.Once
);
_repository.Verify(
mock => mock.PatchAsync(It.IsAny<Expense>(), _cancellationToken),
Times.Once
);
_uow.Verify(mock => mock.SaveChangesAsync(_cancellationToken), Times.Once);
_eventBus.Verify(
mock => mock.PublishAsync(It.IsAny<PatchedExpenseEvent>(), _cancellationToken),
Times.Once
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,18 @@ public async Task PostCategoryCommandHandler_ShouldPostCategoryAndPublishEventAs
await _handler.Handle(postCategoryCommand, _cancellationToken);

// Assert
_validator.Verify();
_repository.Verify();
_uow.Verify();
_eventBus.Verify();
_validator.Verify(
mock => mock.ValidateAsync(It.IsAny<PostCategoryCommand>(), _cancellationToken),
Times.Once
);
_repository.Verify(
mock => mock.PostAsync(It.IsAny<Category>(), _cancellationToken),
Times.Once
);
_uow.Verify(mock => mock.SaveChangesAsync(_cancellationToken), Times.Once);
_eventBus.Verify(
mock => mock.PublishAsync(It.IsAny<PostedCategoryEvent>(), _cancellationToken),
Times.Once
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
namespace Application.UnitTests.Expenses.PostAsync;

public sealed class PostExpenseCommandHandlerTests
{
private readonly CancellationToken _cancellationToken;
private readonly Mock<IValidator<PostExpenseCommand>> _validator;
private readonly Mock<IExpensesRepository> _repository;
private readonly Mock<IUnitOfWork> _uow;
private readonly Mock<IEventBus> _eventBus;
private readonly PostExpenseCommandHandler _handler;

public PostExpenseCommandHandlerTests()
{
_cancellationToken = new();
_validator = new();
_repository = new();
_uow = new();
_eventBus = new();

_handler = new PostExpenseCommandHandler(
_validator.Object,
_repository.Object,
_uow.Object,
_eventBus.Object
);
}

[Fact]
public async Task PostExpenseCommandHandler_ShouldPostExpenseAndPublishEventAsync()
{
// Arrange
var postExpenseCommand = new PostExpenseCommand(
"Expense 1 name",
"Expense 1 description",
1,
new Guid()
);
_validator
.Setup(mock => mock.ValidateAsync(postExpenseCommand, _cancellationToken))
.ReturnsAsync(new ValidationResult())
.Verifiable();
_repository
.Setup(mock => mock.PostAsync(It.IsAny<Expense>(), _cancellationToken))
.Verifiable();
_uow.Setup(mock => mock.SaveChangesAsync(_cancellationToken)).Verifiable();
_eventBus
.Setup(mock => mock.PublishAsync(It.IsAny<PostedExpenseEvent>(), _cancellationToken))
.Verifiable();

// Act
await _handler.Handle(postExpenseCommand, _cancellationToken);

// Assert
_validator.Verify(
mock => mock.ValidateAsync(It.IsAny<PostExpenseCommand>(), _cancellationToken),
Times.Once
);
_repository.Verify(
mock => mock.PostAsync(It.IsAny<Expense>(), _cancellationToken),
Times.Once
);
_uow.Verify(mock => mock.SaveChangesAsync(_cancellationToken), Times.Once);
_eventBus.Verify(
mock => mock.PublishAsync(It.IsAny<PostedExpenseEvent>(), _cancellationToken),
Times.Once
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,17 @@ public GetAllCategoriesQueryHandlerTests()
_handler = new GetAllCategoriesQueryHandler(_repository.Object, _redisCache.Object);
}

[Fact(Skip = "Pending IAsyncQueryProvider mock implementation")]
[Fact]
public async Task GetAllCategoriesQueryHandler_ShouldReturnPagedListOfRequestedCategoriesAsListOfCategoryDTOAndMetadata()
{
// Arrange
var name = "Test";
var containedWord = "es";
var containedWord = "am";
var page = 1;
var pageSize = 2;
var getAllCategoriesQuery = new GetAllCategoriesQuery
{
Page = page,
PageSize = pageSize,
Name = name,
ContainedWord = containedWord,
};
var redisKey = $"{nameof(GetAllCategoriesQuery)}#{page}#{pageSize}";
Expand All @@ -47,17 +45,10 @@ public async Task GetAllCategoriesQueryHandler_ShouldReturnPagedListOfRequestedC
Description = "Description 2",
},
};
var pagedCategories = new PagedList<Category>(
categories,
page,
pageSize,
categories.Count,
false,
false
);
_repository
.Setup(mock => mock.ApplySpecification(It.IsAny<CategoriesSpecification>()))
.Returns(categories.AsQueryable);
.Returns(categories.BuildMock())
.Verifiable();
_redisCache
.Setup(mock => mock.GetCachedData<PagedList<CategoryDTO>>(redisKey))
.ReturnsAsync((PagedList<CategoryDTO>)null!);
Expand Down
Loading

0 comments on commit 182e127

Please sign in to comment.