From 981554d15be1b770b087fe2319ebf988a1b595e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=86=D0=BB=D0=BB=D1=8F=20=D0=A6=D0=B0=D0=BF?= Date: Mon, 11 May 2026 13:06:06 +0300 Subject: [PATCH 1/2] test/21: write tests for BLL/MediatR/Toponyms handlers --- .../Toponyms/GetAllToponymsHandlerTests.cs | 202 +++++++++++++++++ .../Toponyms/GetToponymByIdHandlerTests.cs | 117 ++++++++++ .../GetToponymsByStreetcodeIdHandlerTests.cs | 212 ++++++++++++++++++ 3 files changed, 531 insertions(+) create mode 100644 Streetcode/Streetcode.XUnitTest/BLL/MediatR/Toponyms/GetAllToponymsHandlerTests.cs create mode 100644 Streetcode/Streetcode.XUnitTest/BLL/MediatR/Toponyms/GetToponymByIdHandlerTests.cs create mode 100644 Streetcode/Streetcode.XUnitTest/BLL/MediatR/Toponyms/GetToponymsByStreetcodeIdHandlerTests.cs diff --git a/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Toponyms/GetAllToponymsHandlerTests.cs b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Toponyms/GetAllToponymsHandlerTests.cs new file mode 100644 index 0000000..db8b552 --- /dev/null +++ b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Toponyms/GetAllToponymsHandlerTests.cs @@ -0,0 +1,202 @@ +namespace Streetcode.XUnitTest.BLL.MediatR.Toponyms +{ + using AutoMapper; + using FluentAssertions; + using Moq; + using Streetcode.BLL.DTO.Toponyms; + using Streetcode.BLL.Interfaces.Logging; + using Streetcode.BLL.MediatR.Toponyms.GetAll; + using Streetcode.DAL.Entities.Toponyms; + using Streetcode.DAL.Repositories.Interfaces.Base; + using Streetcode.DAL.Repositories.Interfaces.Toponyms; + using Xunit; + + /// + /// Contains tests for . + /// + public sealed class GetAllToponymsHandlerTests + { + private readonly IMapper mapper; + private readonly Mock loggerMock; + private readonly Mock repositoryWrapperMock; + private readonly Mock toponymRepositoryMock; + private readonly GetAllToponymsHandler handler; + + /// + /// Initializes a new instance of the class. + /// + public GetAllToponymsHandlerTests() + { + this.mapper = new MapperConfiguration(cfg => + { + cfg.CreateMap(); + }).CreateMapper(); + this.loggerMock = new Mock(); + this.repositoryWrapperMock = new Mock(); + this.toponymRepositoryMock = new Mock(); + this.repositoryWrapperMock.Setup(r => r.ToponymRepository).Returns(this.toponymRepositoryMock.Object); + this.handler = new GetAllToponymsHandler(this.repositoryWrapperMock.Object, this.mapper, this.loggerMock.Object); + } + + /// + /// Should return all toponyms when . + /// + /// Awaitable task. + [Fact] + public async Task Handle_ShouldReturnAllToponyms_WhenNoTitleProvided() + { + // Arrange + IQueryable toponyms = new List + { + new() + { + Id = 1, + StreetName = "Шевченка", + }, + new() + { + Id = 2, + StreetName = "Бандери", + }, + }.AsQueryable(); + List expected_toponyms = new() + { + this.mapper.Map(toponyms.ElementAt(0)), + this.mapper.Map(toponyms.ElementAt(1)), + }; + GetAllToponymsQuery query = new(new GetAllToponymsRequestDTO + { + Title = null, + }); + this.toponymRepositoryMock.Setup(r => r.FindAll(null)).Returns(toponyms); + + // Act + var result = await this.handler.Handle(query, CancellationToken.None); + + // Assert + result.IsSuccess.Should().BeTrue(); + result.Value.Toponyms.Should().BeEquivalentTo(expected_toponyms); + this.toponymRepositoryMock.Verify(r => r.FindAll(null), Times.Once); + } + + /// + /// Should return filtered toponyms when . + /// Must be case-insensitive. + /// + /// Awaitable task. + [Fact] + public async Task Handle_ShouldFilterToponyms_WhenTitleProvided_CaseInsensitive() + { + // Arrange + IQueryable toponyms = new List + { + new() + { + Id = 1, + StreetName = "Шевченка", + }, + new() + { + Id = 2, + StreetName = "Бандери", + }, + }.AsQueryable(); + List expected_toponyms = new() + { + this.mapper.Map(toponyms.ElementAt(1)), + }; + GetAllToponymsQuery query = new(new GetAllToponymsRequestDTO + { + Title = "аНдЕр", + }); + this.toponymRepositoryMock.Setup(r => r.FindAll(null)).Returns(toponyms); + + // Act + var result = await this.handler.Handle(query, CancellationToken.None); + + // Assert + result.IsSuccess.Should().BeTrue(); + result.Value.Toponyms.Should().BeEquivalentTo(expected_toponyms); + this.toponymRepositoryMock.Verify(r => r.FindAll(null), Times.Once); + } + + /// + /// Should return unique toponyms when . + /// + /// Awaitable task. + [Fact] + public async Task Handle_ShouldReturnUniqueToponyms_WhenTitleProvided() + { + // Arrange + IQueryable toponyms = new List + { + new() + { + Id = 1, + StreetName = "Шевченка", + Oblast = "Київська", + }, + new() + { + Id = 2, + StreetName = "Шевченка", + Oblast = "Львівська", + }, + }.AsQueryable(); + List expected_toponyms = new() + { + this.mapper.Map(toponyms.ElementAt(0)), + }; + GetAllToponymsQuery query = new(new GetAllToponymsRequestDTO + { + Title = "евч", + }); + this.toponymRepositoryMock.Setup(r => r.FindAll(null)).Returns(toponyms); + + // Act + var result = await this.handler.Handle(query, CancellationToken.None); + + // Assert + result.IsSuccess.Should().BeTrue(); + result.Value.Toponyms.Should().BeEquivalentTo(expected_toponyms); + this.toponymRepositoryMock.Verify(r => r.FindAll(null), Times.Once); + } + + /// + /// Should return empty collection when no matches found. + /// + /// Awaitable task. + [Fact] + public async Task Handle_ShouldReturnEmptyCollection_WhenNoMatchesFound() + { + // Arrange + IQueryable toponyms = new List + { + new() + { + Id = 1, + StreetName = "Шевченка", + }, + new() + { + Id = 2, + StreetName = "Бандери", + }, + }.AsQueryable(); + List expected_toponyms = new(); + GetAllToponymsQuery query = new(new GetAllToponymsRequestDTO + { + Title = "ийськ", + }); + this.toponymRepositoryMock.Setup(r => r.FindAll(null)).Returns(toponyms); + + // Act + var result = await this.handler.Handle(query, CancellationToken.None); + + // Assert + result.IsSuccess.Should().BeTrue(); + result.Value.Toponyms.Should().BeEquivalentTo(expected_toponyms); + this.toponymRepositoryMock.Verify(r => r.FindAll(null), Times.Once); + } + } +} \ No newline at end of file diff --git a/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Toponyms/GetToponymByIdHandlerTests.cs b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Toponyms/GetToponymByIdHandlerTests.cs new file mode 100644 index 0000000..0b88c8a --- /dev/null +++ b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Toponyms/GetToponymByIdHandlerTests.cs @@ -0,0 +1,117 @@ +namespace Streetcode.XUnitTest.BLL.MediatR.Toponyms +{ + using System.Linq.Expressions; + using AutoMapper; + using FluentAssertions; + using Moq; + using Streetcode.BLL.DTO.Toponyms; + using Streetcode.BLL.Interfaces.Logging; + using Streetcode.BLL.MediatR.Toponyms.GetById; + using Streetcode.DAL.Entities.Toponyms; + using Streetcode.DAL.Repositories.Interfaces.Base; + using Streetcode.DAL.Repositories.Interfaces.Toponyms; + using Xunit; + + /// + /// Contains tests for . + /// + public sealed class GetToponymByIdHandlerTests + { + private readonly IMapper mapper; + private readonly Mock loggerMock; + private readonly Mock repositoryWrapperMock; + private readonly Mock toponymRepositoryMock; + private readonly GetToponymByIdHandler handler; + + /// + /// Initializes a new instance of the class. + /// + public GetToponymByIdHandlerTests() + { + this.mapper = new MapperConfiguration(cfg => + { + cfg.CreateMap(); + }).CreateMapper(); + this.loggerMock = new Mock(); + this.repositoryWrapperMock = new Mock(); + this.toponymRepositoryMock = new Mock(); + this.repositoryWrapperMock.Setup(r => r.ToponymRepository).Returns(this.toponymRepositoryMock.Object); + this.handler = new GetToponymByIdHandler(this.repositoryWrapperMock.Object, this.mapper, this.loggerMock.Object); + } + + /// + /// Should return toponym when found by id. + /// + /// Awaitable task. + [Fact] + public async Task Handle_ShouldReturnToponym_WhenFound() + { + // Arrange + Toponym toponym = new() + { + Id = 2, + StreetName = "Бандери", + }; + ToponymDTO expected_toponym = this.mapper.Map(toponym); + GetToponymByIdQuery query = new(2); + this.toponymRepositoryMock.Setup( + r => r.GetFirstOrDefaultAsync( + It.IsAny>>(), + null + ) + ).ReturnsAsync(toponym); + + // Act + var result = await this.handler.Handle(query, CancellationToken.None); + + // Assert + result.IsSuccess.Should().BeTrue(); + result.Value.Should().BeEquivalentTo(expected_toponym); + this.toponymRepositoryMock.Verify( + r => r.GetFirstOrDefaultAsync( + It.IsAny>>(), + null + ), + Times.Once + ); + } + + /// + /// Should return error and log it when toponym not found by id. + /// + /// Awaitable task. + [Fact] + public async Task Handle_ShouldReturnError_WhenNotFound() + { + // Arrange + GetToponymByIdQuery query = new(1); + this.toponymRepositoryMock.Setup( + r => r.GetFirstOrDefaultAsync( + It.IsAny>>(), + null + ) + ).ReturnsAsync(null as Toponym); + this.loggerMock.Setup( + l => l.LogError(query, It.IsAny()) + ); + + // Act + var result = await this.handler.Handle(query, CancellationToken.None); + + // Assert + result.IsSuccess.Should().BeFalse(); + result.Errors.Should().NotBeEmpty(); + this.toponymRepositoryMock.Verify( + r => r.GetFirstOrDefaultAsync( + It.IsAny>>(), + null + ), + Times.Once + ); + this.loggerMock.Verify( + l => l.LogError(query, It.IsAny()), + Times.Once + ); + } + } +} \ No newline at end of file diff --git a/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Toponyms/GetToponymsByStreetcodeIdHandlerTests.cs b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Toponyms/GetToponymsByStreetcodeIdHandlerTests.cs new file mode 100644 index 0000000..e86c58e --- /dev/null +++ b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Toponyms/GetToponymsByStreetcodeIdHandlerTests.cs @@ -0,0 +1,212 @@ +namespace Streetcode.XUnitTest.BLL.MediatR.Toponyms +{ + using AutoMapper; + using Moq; + using Streetcode.BLL.DTO.Toponyms; + using Streetcode.BLL.Interfaces.Logging; + using Streetcode.BLL.MediatR.Toponyms.GetById; + using Streetcode.DAL.Entities.Toponyms; + using Streetcode.DAL.Repositories.Interfaces.Base; + using Streetcode.DAL.Repositories.Interfaces.Toponyms; + using Xunit; + using DAL.Entities.Streetcode; + using Streetcode.BLL.MediatR.Toponyms.GetByStreetcodeId; + using System.Linq.Expressions; + using Microsoft.EntityFrameworkCore.Query; + using Streetcode.BLL.DTO.Streetcode; + using FluentAssertions; + + /// + /// Initializes a new instance of the class. + /// + public sealed class GetToponymsByStreetcodeIdHandlerTests + { + private readonly IMapper mapper; + private readonly Mock loggerMock; + private readonly Mock repositoryWrapperMock; + private readonly Mock toponymRepositoryMock; + private readonly GetToponymsByStreetcodeIdHandler handler; + + /// + /// Initializes a new instance of the class. + /// + public GetToponymsByStreetcodeIdHandlerTests() + { + this.mapper = new MapperConfiguration(cfg => + { + cfg.CreateMap(); + cfg.CreateMap(); + }).CreateMapper(); + this.loggerMock = new Mock(); + this.repositoryWrapperMock = new Mock(); + this.toponymRepositoryMock = new Mock(); + this.repositoryWrapperMock.Setup(r => r.ToponymRepository).Returns(this.toponymRepositoryMock.Object); + this.handler = new GetToponymsByStreetcodeIdHandler(this.repositoryWrapperMock.Object, this.mapper, this.loggerMock.Object); + } + + /// + /// Should return toponyms when found by streetcode id. + /// + /// Awaitable task. + [Fact] + public async Task Handle_ShouldReturnToponyms_WhenFound() + { + // Arrange + List toponyms = new() + { + new() + { + Id = 1, + StreetName = "Шевченка", + Oblast = "Київська", + Streetcodes = new List() + { + new() + { + Id = 1, + }, + new() + { + Id = 2, + }, + }, + }, + }; + List expected_toponyms = new() + { + this.mapper.Map(toponyms[0]), + }; + GetToponymsByStreetcodeIdQuery query = new(1); + this.toponymRepositoryMock.Setup( + r => r.GetAllAsync( + It.IsAny>>(), + It.IsAny, IIncludableQueryable>>() + ) + ).ReturnsAsync(toponyms); + + // Act + var result = await this.handler.Handle(query, CancellationToken.None); + + // Assert + result.IsSuccess.Should().BeTrue(); + result.Value.Should().BeEquivalentTo(expected_toponyms); + this.toponymRepositoryMock.Verify( + r => r.GetAllAsync( + It.IsAny>>(), + It.IsAny, IIncludableQueryable>>() + ), + Times.Once + ); + } + + /// + /// Should return toponyms with unique street name when found by streetcode id. + /// + /// Awaitable task. + [Fact] + public async Task Handle_ShouldReturnUniqueToponyms_WhenFound() + { + // Arrange + List toponyms = new() + { + new() + { + Id = 1, + StreetName = "Шевченка", + Oblast = "Київська", + Streetcodes = new List() + { + new() + { + Id = 1, + }, + new() + { + Id = 2, + }, + }, + }, + new() + { + Id = 2, + StreetName = "Шевченка", + Oblast = "Львівська", + Streetcodes = new List() + { + new() + { + Id = 1, + }, + new() + { + Id = 2, + }, + }, + }, + }; + List expected_toponyms = new() + { + this.mapper.Map(toponyms[0]), + }; + GetToponymsByStreetcodeIdQuery query = new(1); + this.toponymRepositoryMock.Setup( + r => r.GetAllAsync( + It.IsAny>>(), + It.IsAny, IIncludableQueryable>>() + ) + ).ReturnsAsync(toponyms); + + // Act + var result = await this.handler.Handle(query, CancellationToken.None); + + // Assert + result.IsSuccess.Should().BeTrue(); + result.Value.Should().BeEquivalentTo(expected_toponyms); + this.toponymRepositoryMock.Verify( + r => r.GetAllAsync( + It.IsAny>>(), + It.IsAny, IIncludableQueryable>>() + ), + Times.Once + ); + } + + /// + /// Should return error and log it when toponyms not found by streetcode id. + /// + /// Awaitable task. + [Fact] + public async Task Handle_ShouldReturnError_WhenNotFound() + { + // Arrange + GetToponymsByStreetcodeIdQuery query = new(3); + this.toponymRepositoryMock.Setup( + r => r.GetAllAsync( + It.IsAny>>(), + It.IsAny, IIncludableQueryable>>() + ) + ).ReturnsAsync(Enumerable.Empty()); + this.loggerMock.Setup( + l => l.LogError(query, It.IsAny()) + ); + + // Act + var result = await this.handler.Handle(query, CancellationToken.None); + + // Assert + result.IsSuccess.Should().BeFalse(); + result.Errors.Should().NotBeEmpty(); + this.toponymRepositoryMock.Verify( + r => r.GetAllAsync( + It.IsAny>>(), + It.IsAny, IIncludableQueryable>>() + ), + Times.Once + ); + this.loggerMock.Verify( + l => l.LogError(query, It.IsAny()), + Times.Once + ); + } + } +} \ No newline at end of file From 5567240db1a3e05d5e33a39315bec44e7dc39412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=86=D0=BB=D0=BB=D1=8F=20=D0=A6=D0=B0=D0=BF?= Date: Mon, 11 May 2026 21:13:09 +0300 Subject: [PATCH 2/2] fix/44: adjust tests for GetToponymsByStreetcodeIdHandler matching changes in #45 --- .../GetToponymsByStreetcodeIdHandlerTests.cs | 48 ++++++++----------- 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Toponyms/GetToponymsByStreetcodeIdHandlerTests.cs b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Toponyms/GetToponymsByStreetcodeIdHandlerTests.cs index e86c58e..8f66b84 100644 --- a/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Toponyms/GetToponymsByStreetcodeIdHandlerTests.cs +++ b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Toponyms/GetToponymsByStreetcodeIdHandlerTests.cs @@ -52,7 +52,7 @@ public GetToponymsByStreetcodeIdHandlerTests() public async Task Handle_ShouldReturnToponyms_WhenFound() { // Arrange - List toponyms = new() + IQueryable toponyms = new List() { new() { @@ -71,18 +71,17 @@ public async Task Handle_ShouldReturnToponyms_WhenFound() }, }, }, - }; + }.AsQueryable(); List expected_toponyms = new() { - this.mapper.Map(toponyms[0]), + this.mapper.Map(toponyms.First()), }; GetToponymsByStreetcodeIdQuery query = new(1); this.toponymRepositoryMock.Setup( - r => r.GetAllAsync( - It.IsAny>>(), - It.IsAny, IIncludableQueryable>>() + r => r.FindAll( + It.IsAny>>() ) - ).ReturnsAsync(toponyms); + ).Returns(toponyms); // Act var result = await this.handler.Handle(query, CancellationToken.None); @@ -91,9 +90,8 @@ public async Task Handle_ShouldReturnToponyms_WhenFound() result.IsSuccess.Should().BeTrue(); result.Value.Should().BeEquivalentTo(expected_toponyms); this.toponymRepositoryMock.Verify( - r => r.GetAllAsync( - It.IsAny>>(), - It.IsAny, IIncludableQueryable>>() + r => r.FindAll( + It.IsAny>>() ), Times.Once ); @@ -107,7 +105,7 @@ public async Task Handle_ShouldReturnToponyms_WhenFound() public async Task Handle_ShouldReturnUniqueToponyms_WhenFound() { // Arrange - List toponyms = new() + IQueryable toponyms = new List() { new() { @@ -143,18 +141,17 @@ public async Task Handle_ShouldReturnUniqueToponyms_WhenFound() }, }, }, - }; + }.AsQueryable(); List expected_toponyms = new() { - this.mapper.Map(toponyms[0]), + this.mapper.Map(toponyms.First()), }; GetToponymsByStreetcodeIdQuery query = new(1); this.toponymRepositoryMock.Setup( - r => r.GetAllAsync( - It.IsAny>>(), - It.IsAny, IIncludableQueryable>>() + r => r.FindAll( + It.IsAny>>() ) - ).ReturnsAsync(toponyms); + ).Returns(toponyms); // Act var result = await this.handler.Handle(query, CancellationToken.None); @@ -163,9 +160,8 @@ public async Task Handle_ShouldReturnUniqueToponyms_WhenFound() result.IsSuccess.Should().BeTrue(); result.Value.Should().BeEquivalentTo(expected_toponyms); this.toponymRepositoryMock.Verify( - r => r.GetAllAsync( - It.IsAny>>(), - It.IsAny, IIncludableQueryable>>() + r => r.FindAll( + It.IsAny>>() ), Times.Once ); @@ -181,11 +177,10 @@ public async Task Handle_ShouldReturnError_WhenNotFound() // Arrange GetToponymsByStreetcodeIdQuery query = new(3); this.toponymRepositoryMock.Setup( - r => r.GetAllAsync( - It.IsAny>>(), - It.IsAny, IIncludableQueryable>>() + r => r.FindAll( + It.IsAny>>() ) - ).ReturnsAsync(Enumerable.Empty()); + ).Returns(Enumerable.Empty().AsQueryable()); this.loggerMock.Setup( l => l.LogError(query, It.IsAny()) ); @@ -197,9 +192,8 @@ public async Task Handle_ShouldReturnError_WhenNotFound() result.IsSuccess.Should().BeFalse(); result.Errors.Should().NotBeEmpty(); this.toponymRepositoryMock.Verify( - r => r.GetAllAsync( - It.IsAny>>(), - It.IsAny, IIncludableQueryable>>() + r => r.FindAll( + It.IsAny>>() ), Times.Once );