Skip to content

Commit 64fb3f0

Browse files
committed
test: Add new tests for GetCompanyByIdQueryHandler
1 parent b8cffdb commit 64fb3f0

File tree

1 file changed

+312
-0
lines changed

1 file changed

+312
-0
lines changed
Lines changed: 312 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,312 @@
1+
using System.Linq.Expressions;
2+
using Bogus.Extensions.Brazil;
3+
using FluentAssertions;
4+
using Moq;
5+
using SnackFlow.Application.Exceptions;
6+
using SnackFlow.Application.Extensions;
7+
using SnackFlow.Application.Features.Companies.Queries.GetCompanyById;
8+
using SnackFlow.Domain.Constants;
9+
using SnackFlow.Domain.Entities;
10+
using SnackFlow.Domain.Enums;
11+
using SnackFlow.Domain.Repositories;
12+
using SnackFlow.Domain.Tests;
13+
using SnackFlow.Domain.ValueObjects.CompanyName;
14+
using SnackFlow.Domain.ValueObjects.Email;
15+
using SnackFlow.Domain.ValueObjects.Phone;
16+
using SnackFlow.Domain.ValueObjects.TaxId;
17+
18+
namespace SnackFlow.Application.Tests.Features.Companies.Queries;
19+
20+
public class GetCompanyByIdQueryHandlerUnitTests : BaseTest
21+
{
22+
#region Setup
23+
24+
private readonly Mock<IUnitOfWork> _mockUnitOfWork;
25+
private readonly Mock<ICompanyRepository> _mockCompanyRepository;
26+
private readonly GetCompanyByIdQueryHandler _queryHandler;
27+
private readonly GetCompanyByIdQuery _query;
28+
private readonly Company _company;
29+
30+
public GetCompanyByIdQueryHandlerUnitTests()
31+
{
32+
_mockUnitOfWork = new Mock<IUnitOfWork>();
33+
_mockCompanyRepository = new Mock<ICompanyRepository>();
34+
_queryHandler = new GetCompanyByIdQueryHandler(_mockUnitOfWork.Object);
35+
36+
_company = Company.Create(
37+
CompanyName.Create(_faker.Person.FullName, _faker.Company.CompanyName()),
38+
TaxId.Create(_faker.Company.Cnpj(), TaxIdType.LegalEntityWithCnpj),
39+
Email.Create(_faker.Person.Email.ToLowerInvariant()),
40+
Phone.Create(_faker.Phone.PhoneNumber("(92) 9####-####"))
41+
);
42+
43+
_query = new GetCompanyByIdQuery(_company.Id);
44+
}
45+
46+
#endregion
47+
48+
#region Success Tests
49+
50+
[Fact(DisplayName = "Should return company successfully when company exists")]
51+
public async Task Handle_WhenCompanyExists_ShouldReturnCompanySuccessfully()
52+
{
53+
// Arrange
54+
_mockCompanyRepository
55+
.Setup(x => x.GetSingleAsync(
56+
It.IsAny<Expression<Func<Company, bool>>>(),
57+
It.IsAny<CancellationToken>()
58+
))
59+
.ReturnsAsync(_company);
60+
61+
_mockUnitOfWork
62+
.Setup(x => x.Companies)
63+
.Returns(_mockCompanyRepository.Object);
64+
65+
// Act
66+
var result = await _queryHandler.Handle(_query, CancellationToken.None);
67+
68+
// Assert
69+
result.IsSuccess.Should().BeTrue();
70+
result.IsFailure.Should().BeFalse();
71+
result.Value.Should().NotBeNull();
72+
result.Value.CorporateName.Should().Be(_company.Name.Corporate);
73+
result.Value.FantasyName.Should().Be(_company.Name.Fantasy);
74+
result.Value.Email.Should().Be(_company.Email);
75+
result.Value.Phone.Should().Be(_company.Phone);
76+
result.Value.TaxId.Should().Be(_company.TaxId);
77+
result.Value.Type.Should().Be(_company.TaxId.Type.GetDescription());
78+
79+
_mockCompanyRepository.Verify(x => x.GetSingleAsync(
80+
It.IsAny<Expression<Func<Company, bool>>>(),
81+
It.IsAny<CancellationToken>()), Times.Once);
82+
}
83+
84+
#endregion
85+
86+
#region Not Found Tests
87+
88+
[Fact(DisplayName = "Should throw not found exception when company does not exist")]
89+
public async Task Handle_WhenCompanyDoesNotExist_ShouldThrowNotFoundException()
90+
{
91+
// Arrange
92+
_mockCompanyRepository
93+
.Setup(x => x.GetSingleAsync(
94+
It.IsAny<Expression<Func<Company, bool>>>(),
95+
It.IsAny<CancellationToken>()
96+
))
97+
.ReturnsAsync((Company?)null);
98+
99+
_mockUnitOfWork
100+
.Setup(x => x.Companies)
101+
.Returns(_mockCompanyRepository.Object);
102+
103+
// Act
104+
var result = async () => await _queryHandler.Handle(_query, CancellationToken.None);
105+
106+
// Assert
107+
await result.Should()
108+
.ThrowAsync<NotFoundException>()
109+
.WithMessage(ErrorMessage.NotFound.Company);
110+
111+
_mockCompanyRepository.Verify(x => x.GetSingleAsync(
112+
It.IsAny<Expression<Func<Company, bool>>>(),
113+
It.IsAny<CancellationToken>()), Times.Once);
114+
}
115+
116+
[Fact(DisplayName = "Should throw not found exception when company id is empty")]
117+
public async Task Handle_WhenCompanyIdIsEmpty_ShouldThrowNotFoundException()
118+
{
119+
// Arrange
120+
var emptyQuery = new GetCompanyByIdQuery(Guid.Empty);
121+
122+
_mockCompanyRepository
123+
.Setup(x => x.GetSingleAsync(
124+
It.IsAny<Expression<Func<Company, bool>>>(),
125+
It.IsAny<CancellationToken>()
126+
))
127+
.ReturnsAsync((Company?)null);
128+
129+
_mockUnitOfWork
130+
.Setup(x => x.Companies)
131+
.Returns(_mockCompanyRepository.Object);
132+
133+
// Act
134+
var result = async () => await _queryHandler.Handle(emptyQuery, CancellationToken.None);
135+
136+
// Assert
137+
await result.Should()
138+
.ThrowAsync<NotFoundException>()
139+
.WithMessage(ErrorMessage.NotFound.Company);
140+
141+
_mockCompanyRepository.Verify(x => x.GetSingleAsync(
142+
It.IsAny<Expression<Func<Company, bool>>>(),
143+
It.IsAny<CancellationToken>()), Times.Once);
144+
}
145+
146+
#endregion
147+
148+
#region Cancellation Tests
149+
150+
[Fact(DisplayName = "Should respect cancellation token during repository call")]
151+
public async Task Handle_WhenCancellationTokenDuringRepositoryCall_ShouldRespectCancellationToken()
152+
{
153+
// Arrange
154+
var mockCancellationToken = new CancellationToken(true);
155+
156+
_mockCompanyRepository
157+
.Setup(x => x.GetSingleAsync(
158+
It.IsAny<Expression<Func<Company, bool>>>(),
159+
It.Is<CancellationToken>(ct => ct.IsCancellationRequested)))
160+
.ThrowsAsync(new OperationCanceledException());
161+
162+
_mockUnitOfWork
163+
.Setup(x => x.Companies)
164+
.Returns(_mockCompanyRepository.Object);
165+
166+
// Act
167+
var result = async () => await _queryHandler.Handle(_query, mockCancellationToken);
168+
169+
// Assert
170+
await result.Should()
171+
.ThrowAsync<OperationCanceledException>();
172+
173+
_mockCompanyRepository.Verify(x => x.GetSingleAsync(
174+
It.IsAny<Expression<Func<Company, bool>>>(),
175+
It.Is<CancellationToken>(ct => ct.IsCancellationRequested)),
176+
Times.Once);
177+
}
178+
179+
#endregion
180+
181+
#region Repository Verification Tests
182+
183+
[Fact(DisplayName = "Should call repository with correct expression")]
184+
public async Task Handle_WhenCalled_ShouldCallRepositoryWithCorrectExpression()
185+
{
186+
// Arrange
187+
Expression<Func<Company, bool>>? capturedExpression = null;
188+
189+
_mockCompanyRepository
190+
.Setup(x => x.GetSingleAsync(
191+
It.IsAny<Expression<Func<Company, bool>>>(),
192+
It.IsAny<CancellationToken>(),
193+
It.IsAny<Expression<Func<Company, object>>[]>()
194+
))
195+
.Callback<Expression<Func<Company, bool>>, CancellationToken, Expression<Func<Company, object>>[]>(
196+
(expr, ct, includes) =>
197+
{
198+
capturedExpression = expr;
199+
})
200+
.ReturnsAsync(_company);
201+
202+
_mockUnitOfWork
203+
.Setup(x => x.Companies)
204+
.Returns(_mockCompanyRepository.Object);
205+
206+
// Act
207+
await _queryHandler.Handle(_query, CancellationToken.None);
208+
209+
// Assert
210+
capturedExpression.Should().NotBeNull();
211+
212+
var compiledExpression = capturedExpression!.Compile();
213+
compiledExpression(_company).Should().BeTrue();
214+
215+
var differentCompany = Company.Create(
216+
CompanyName.Create(_faker.Person.FullName, _faker.Company.CompanyName()),
217+
TaxId.Create(_faker.Company.Cnpj(), TaxIdType.LegalEntityWithCnpj),
218+
Email.Create(_faker.Person.Email.ToLowerInvariant()),
219+
Phone.Create(_faker.Phone.PhoneNumber("(92) 9####-####"))
220+
);
221+
222+
compiledExpression(differentCompany).Should().BeFalse();
223+
}
224+
225+
#endregion
226+
227+
#region Repository Verification Tests - Alternative with includes parameter
228+
229+
[Fact(DisplayName = "Should call repository with correct expression including includes parameter")]
230+
public async Task Handle_WhenCalledWithIncludes_ShouldCallRepositoryWithCorrectExpression()
231+
{
232+
// Arrange
233+
Expression<Func<Company, bool>>? capturedExpression = null;
234+
235+
_mockCompanyRepository
236+
.Setup(x => x.GetSingleAsync(
237+
It.IsAny<Expression<Func<Company, bool>>>(),
238+
It.IsAny<CancellationToken>(),
239+
It.IsAny<Expression<Func<Company, object>>[]>()
240+
))
241+
.Callback<Expression<Func<Company, bool>>, CancellationToken, Expression<Func<Company, object>>[]>(
242+
(expr, ct, includes) =>
243+
{
244+
capturedExpression = expr;
245+
})
246+
.ReturnsAsync(_company);
247+
248+
_mockUnitOfWork
249+
.Setup(x => x.Companies)
250+
.Returns(_mockCompanyRepository.Object);
251+
252+
// Act
253+
await _queryHandler.Handle(_query, CancellationToken.None);
254+
255+
// Assert
256+
capturedExpression.Should().NotBeNull();
257+
258+
var compiledExpression = capturedExpression!.Compile();
259+
compiledExpression(_company).Should().BeTrue();
260+
261+
var differentCompany = Company.Create(
262+
CompanyName.Create(_faker.Person.FullName, _faker.Company.CompanyName()),
263+
TaxId.Create(_faker.Company.Cnpj(), TaxIdType.LegalEntityWithCnpj),
264+
Email.Create(_faker.Person.Email.ToLowerInvariant()),
265+
Phone.Create(_faker.Phone.PhoneNumber("(92) 9####-####"))
266+
);
267+
268+
compiledExpression(differentCompany).Should().BeFalse();
269+
}
270+
271+
#endregion
272+
273+
#region Response Mapping Tests
274+
275+
[Fact(DisplayName = "Should map all company properties correctly to response")]
276+
public async Task Handle_WhenCompanyExists_ShouldMapAllPropertiesCorrectly()
277+
{
278+
// Arrange
279+
_mockCompanyRepository
280+
.Setup(x => x.GetSingleAsync(
281+
It.IsAny<Expression<Func<Company, bool>>>(),
282+
It.IsAny<CancellationToken>()
283+
))
284+
.ReturnsAsync(_company);
285+
286+
_mockUnitOfWork
287+
.Setup(x => x.Companies)
288+
.Returns(_mockCompanyRepository.Object);
289+
290+
// Act
291+
var result = await _queryHandler.Handle(_query, CancellationToken.None);
292+
293+
// Assert
294+
result.Value.Should().NotBeNull();
295+
296+
result.Value.CorporateName.Should().Be(_company.Name.Corporate);
297+
result.Value.FantasyName.Should().Be(_company.Name.Fantasy);
298+
result.Value.Email.Should().Be(_company.Email);
299+
result.Value.Phone.Should().Be(_company.Phone);
300+
result.Value.TaxId.Should().Be(_company.TaxId);
301+
result.Value.Type.Should().Be(_company.TaxId.Type.GetDescription());
302+
303+
result.Value.CorporateName.Should().NotBeNullOrEmpty();
304+
result.Value.FantasyName.Should().NotBeNullOrEmpty();
305+
result.Value.Email.Should().NotBeNullOrEmpty();
306+
result.Value.Phone.Should().NotBeNullOrEmpty();
307+
result.Value.TaxId.Should().NotBeNullOrEmpty();
308+
result.Value.Type.Should().NotBeNullOrEmpty();
309+
}
310+
311+
#endregion
312+
}

0 commit comments

Comments
 (0)