diff --git a/Govor.API.Tests/IntegrationTests/EF/Repositories/UsersRepositoryTests.cs b/Govor.API.Tests/IntegrationTests/EF/Repositories/UsersRepositoryTests.cs index be69968..c70dcff 100644 --- a/Govor.API.Tests/IntegrationTests/EF/Repositories/UsersRepositoryTests.cs +++ b/Govor.API.Tests/IntegrationTests/EF/Repositories/UsersRepositoryTests.cs @@ -3,6 +3,7 @@ using Govor.Core.Infrastructure.Validators; using Govor.Core.Models; using Govor.Data; using Govor.Data.Repositories; +using Govor.Data.Repositories.Exceptions; using Microsoft.EntityFrameworkCore; namespace Govor.API.Tests.IntegrationTests.EF.Repositories; @@ -53,5 +54,75 @@ public class UsersRepositoryTests Assert.That(result.Count, Is.EqualTo(users.Count)); Assert.That(result.Select(u => u.Id), Is.EquivalentTo(users.Select(u => u.Id))); Assert.That(result.Select(u => u.Username), Is.EquivalentTo(users.Select(u => u.Username))); - } + } + + [Test] + public async Task Given_ValidUserId_When_FindById_Then_Returns_User() + { + // Arrange + var user = _fixture.Create(); + await using var context = new GovorDbContext(_options); + var userRepository = new UsersRepository(context, _userValidator); + + context.Users.Add(user); + await context.SaveChangesAsync(); + + // Act + var result = await userRepository.FindById(user.Id); + + // Assert + Assert.That(result, Is.Not.Null); + Assert.That(result.Username, Is.EqualTo(user.Username)); + Assert.That(result.Id, Is.EqualTo(user.Id)); + } + + [Test] + public async Task Given_InvalidUserId_When_FindById_Should_Throw_NotFoundException() + { + // Arrange + var id = Guid.NewGuid(); + + await using var context = new GovorDbContext(_options); + var userRepository = new UsersRepository(context, _userValidator); + + // Act & Assert + Assert.ThrowsAsync>(async () => await userRepository.FindById(id)); + } + + [Test] + public async Task Given_RangeValidUserId_When_FindByRangeId_Then_Returns_Users() + { + // Arrange + var random = new Random(); + var users = _fixture.CreateMany(random.Next(2, 10)).ToList(); + + await using var context = new GovorDbContext(_options); + var userRepository = new UsersRepository(context, _userValidator); + + context.Users.AddRange(users); + await context.SaveChangesAsync(); + + // Act + var result = await userRepository.FindByRangeId(users.Select(u => u.Id)); + + // Assert + Assert.That(result, Is.Not.Null); + Assert.That(result.Count, Is.EqualTo(users.Count)); + Assert.That(result.Select(r => r.Id), Is.EquivalentTo(users.Select(u => u.Id))); + Assert.That(result.Select(u => u.Username), Is.EquivalentTo(users.Select(u => u.Username))); + } + + [Test] + public async Task Given_InvalidRangeId_When_FindByRangeId_Should_Throw_NotFoundException() + { + // Arrange + var random = new Random(); + var ids = _fixture.CreateMany(random.Next(2, 10)).ToList(); + + await using var context = new GovorDbContext(_options); + var userRepository = new UsersRepository(context, _userValidator); + + // Act & Assert + Assert.ThrowsAsync>>(async () => await userRepository.FindByRangeId(ids)); + } } \ No newline at end of file diff --git a/Govor.Core/Govor.Core.csproj b/Govor.Core/Govor.Core.csproj index b9fad79..71fa877 100644 --- a/Govor.Core/Govor.Core.csproj +++ b/Govor.Core/Govor.Core.csproj @@ -10,4 +10,8 @@ + + + + diff --git a/Govor.Core/Infrastructure/Extensions/QueryableExtensions.cs b/Govor.Core/Infrastructure/Extensions/QueryableExtensions.cs new file mode 100644 index 0000000..e380f41 --- /dev/null +++ b/Govor.Core/Infrastructure/Extensions/QueryableExtensions.cs @@ -0,0 +1,13 @@ +using Microsoft.EntityFrameworkCore; + +namespace Govor.Core.Infrastructure.Extensions; + +public static class QueryableExtensions +{ + public static async Task> ToListOrThrowIfEmpty(this IQueryable query, Exception ex) + { + var list = await query.ToListAsync(); + if (list.Count == 0) throw ex; + return list; + } +} diff --git a/Govor.Core/Repositories/IUsersReader.cs b/Govor.Core/Repositories/IUsersReader.cs index 6811e95..e8ec196 100644 --- a/Govor.Core/Repositories/IUsersReader.cs +++ b/Govor.Core/Repositories/IUsersReader.cs @@ -6,9 +6,8 @@ public interface IUsersReader { public Task> GetAll(); public Task FindById(Guid id); - public Task> FindByRangeId(IEnumerable ids); - public Task FindByUsername(string username); - public Task> FindByRangeUsername(IEnumerable usernames); - - public Task> FindUsersByCreatedDate(DateOnly createdDate); + public Task> FindByRangeId(IEnumerable ids); + public Task> FindUsersByName(string username); + public Task> FindByRangeUsername(IEnumerable usernames); + public Task> FindUsersByCreatedDate(DateOnly createdDate); } \ No newline at end of file diff --git a/Govor.Data/Repositories/Exceptions/NotFoundByKeyException.cs b/Govor.Data/Repositories/Exceptions/NotFoundByKeyException.cs new file mode 100644 index 0000000..08f6c8b --- /dev/null +++ b/Govor.Data/Repositories/Exceptions/NotFoundByKeyException.cs @@ -0,0 +1,14 @@ +namespace Govor.Data.Repositories.Exceptions; + +public class NotFoundByKeyException : NotFoundException +{ + public NotFoundByKeyException(T key) + : base($"Not found object by {key}"){} + + public NotFoundByKeyException(T id, string message) + : base($"Not found object by {id}. Message: " + message) {} + + public NotFoundByKeyException(string message, Exception innerException) : base(message, innerException) + { + } +} \ No newline at end of file diff --git a/Govor.Data/Repositories/Exceptions/NotFoundException.cs b/Govor.Data/Repositories/Exceptions/NotFoundException.cs new file mode 100644 index 0000000..dc60ca5 --- /dev/null +++ b/Govor.Data/Repositories/Exceptions/NotFoundException.cs @@ -0,0 +1,11 @@ +using Govor.Core; + +namespace Govor.Data.Repositories.Exceptions; + +public class NotFoundException : GovorCoreException +{ + public NotFoundException(string message) + : base(message) {} + public NotFoundException(string message, Exception innerException) + : base(message, innerException){} +} \ No newline at end of file diff --git a/Govor.Data/Repositories/UsersRepository.cs b/Govor.Data/Repositories/UsersRepository.cs index 303c368..a0feee6 100644 --- a/Govor.Data/Repositories/UsersRepository.cs +++ b/Govor.Data/Repositories/UsersRepository.cs @@ -1,6 +1,8 @@ +using Govor.Core.Infrastructure.Extensions; using Govor.Core.Infrastructure.Validators; using Govor.Core.Models; using Govor.Core.Repositories; +using Govor.Data.Repositories.Exceptions; using Microsoft.EntityFrameworkCore; namespace Govor.Data.Repositories; @@ -23,27 +25,39 @@ public class UsersRepository : IUsersRepository .ToListAsync(); } - public Task FindById(Guid id) + public async Task FindById(Guid id) { - throw new NotImplementedException(); + return await _context.Users + .AsNoTracking() + .FirstOrDefaultAsync(x => x.Id == id) + ?? throw new NotFoundByKeyException(id, "User with given id does not exist"); } - public Task> FindByRangeId(IEnumerable ids) + public async Task> FindByRangeId(IEnumerable ids) { - throw new NotImplementedException(); + return await _context.Users + .AsNoTracking() + .Where(x => ids.Contains(x.Id)) + .ToListOrThrowIfEmpty(new NotFoundByKeyException>(ids,"Users with given ids not found")); + } + + public async Task> FindUsersByName(string username) + { + return await _context.Users + .AsNoTracking() + .Where(x => x.Username == username) + .ToListOrThrowIfEmpty(new NotFoundByKeyException(username, "Users with given username not found")); + } + + public async Task> FindByRangeUsername(IEnumerable usernames) + { + return await _context.Users + .AsNoTracking() + .Where(x => usernames.Contains(x.Username)) + .ToListOrThrowIfEmpty(new NotFoundByKeyException>(usernames, "Users with given usernames not found")); } - public Task FindByUsername(string username) - { - throw new NotImplementedException(); - } - - public Task> FindByRangeUsername(IEnumerable usernames) - { - throw new NotImplementedException(); - } - - public Task> FindUsersByCreatedDate(DateOnly createdDate) + public Task> FindUsersByCreatedDate(DateOnly createdDate) { throw new NotImplementedException(); }