InvitesRepositoryTests

+ other reworks
This commit is contained in:
Artemy
2025-06-24 19:17:27 +07:00
parent 80e2ec30c6
commit f99ec0b17b
12 changed files with 378 additions and 23 deletions
@@ -91,6 +91,7 @@ public class AdminsRepositoryTests
[Test]
public async Task Given_InvalidUserId_When_GetByIdAsync_Should_Throw_NotFoundByKeyException()
{
// Arrange
await using var context = new GovorDbContext(_options);
var repository = new AdminsRepository(context, _validator);
@@ -0,0 +1,244 @@
using AutoFixture;
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;
[TestFixture]
public class InvitesRepositoryTests
{
private Fixture _fixture;
private DbContextOptions<GovorDbContext> _options;
private IObjectValidator<Invitation> _validator = new InvitationValidator();
private int _testIteration = 0;
[SetUp]
public void Setup()
{
_fixture = new Fixture();
_fixture.Behaviors
.OfType<ThrowingRecursionBehavior>()
.ToList()
.ForEach(b => _fixture.Behaviors.Remove(b));
_fixture.Behaviors.Add(new OmitOnRecursionBehavior());
_options = new DbContextOptionsBuilder<GovorDbContext>()
.UseInMemoryDatabase(databaseName: $"DbGovor_{nameof(InvitesRepositoryTests)}_{_testIteration}")
.Options;
_testIteration += 1;
}
[Test]
public async Task Given_NotEmptyDbSet_When_GetAllAsync_Then_Invites_Are_Returned()
{
// Arrange
var random = new Random();
var invitations = _fixture.CreateMany<Invitation>(random.Next(3, 10)).ToList();
await using var context = new GovorDbContext(_options);
var repository = new InvitesRepository(context, _validator);
context.Invitations.AddRange(invitations);
await context.SaveChangesAsync();
// Act
var result = await repository.GetAllAsync();
// Assert
Assert.That(result, Is.Not.Null);
Assert.That(result.Count(), Is.EqualTo(invitations.Count()));
Assert.That(result, Is.EquivalentTo(invitations));
}
[Test]
public async Task Given_EmptyDbSet_When_GetAllAsync_Should_Throw_NotFoundException()
{
// Arrange
await using var context = new GovorDbContext(_options);
var repository = new InvitesRepository(context, _validator);
// Act & Assert
Assert.ThrowsAsync<NotFoundException>(async () => await repository.GetAllAsync());
}
[Test]
public async Task Given_ValidInvitesId_When_FindByIdAsync_Then_Invites_Are_Returned()
{
// Arrange
var invitation = _fixture.Create<Invitation>();
await using var context = new GovorDbContext(_options);
var repository = new InvitesRepository(context, _validator);
context.Invitations.Add(invitation);
await context.SaveChangesAsync();
// Act
var result = await repository.FindByIdAsync(invitation.Id);
// Assert
Assert.That(result, Is.Not.Null);
Assert.That(result.Id, Is.EqualTo(invitation.Id));
}
[Test]
public async Task Given_InvalidInvitesId_When_FindByIdAsync_Should_Throw_NotFoundByKeyException()
{
// Arrange
await using var context = new GovorDbContext(_options);
var repository = new InvitesRepository(context, _validator);
// Act & Assert
Assert.ThrowsAsync<NotFoundByKeyException<Guid>>(async () => await repository.FindByIdAsync(Guid.Empty));
}
[Test]
public async Task Given_ValidInvitesCode_When_FindByCodeAsync_Then_Invites_Are_Returned()
{
// Arrange
var invitation = _fixture.Create<Invitation>();
await using var context = new GovorDbContext(_options);
var repository = new InvitesRepository(context, _validator);
context.Invitations.Add(invitation);
await context.SaveChangesAsync();
// Act
var result = await repository.FindByCodeAsync(invitation.Code);
// Assert
Assert.That(result, Is.Not.Null);
Assert.That(result.Id, Is.EqualTo(invitation.Id));
}
[Test]
public async Task Given_InvalidCode_When_FindByCodeAsync_Should_Throw_NotFoundByKeyException()
{
// Arrange
await using var context = new GovorDbContext(_options);
var repository = new InvitesRepository(context, _validator);
// Act & Assert
Assert.ThrowsAsync<NotFoundByKeyException<string>>(async () => await repository.FindByCodeAsync(_fixture.Create<string>()));
}
[Test]
public async Task Given_ValidAdminInvites_When_FindAdminsInvitesAsync_Then_Invites_Are_Returned()
{
// Arrange
var random = new Random();
var invitations = _fixture.CreateMany<Invitation>(random.Next(3, 10)).ToList();
foreach (var inv in invitations)
{
inv.IsAdmin = true;
}
await using var context = new GovorDbContext(_options);
var repository = new InvitesRepository(context, _validator);
context.Invitations.AddRange(invitations);
await context.SaveChangesAsync();
// Act
var result = await repository.FindAdminsInvitesAsync();
// Assert
Assert.That(result, Is.Not.Null);
Assert.That(result.Count(), Is.EqualTo(invitations.Count()));
Assert.That(result, Is.EquivalentTo(invitations));
}
[Test]
public async Task Given_InvalidAdminsInvites_When_FindAdminsInvitesAsync_Should_Throw_NotFoundByKeyException()
{
// Arrange
await using var context = new GovorDbContext(_options);
var repository = new InvitesRepository(context, _validator);
// Act & Assert
Assert.ThrowsAsync<NotFoundByKeyException<bool>>(async () => await repository.FindAdminsInvitesAsync());
}
[Test]
public async Task Given_ValidAdmin_When_AddAsync_Then_Added()
{
// Arrange
var invitation = _fixture.Create<Invitation>();
invitation.Code = string.Join("", _fixture.CreateMany<char>(12));
invitation.EndDate = invitation.DateCreated.AddHours(1);
await using var context = new GovorDbContext(_options);
var repository = new InvitesRepository(context, _validator);
// Act
await repository.AddAsync(invitation);
// Assert
Assert.That(context.Invitations.Count, Is.EqualTo(1));
Assert.That(context.Invitations.First(), Is.EqualTo(invitation));
}
[Test]
public async Task Given_InvalidAdmin_When_AddAsync_Should_Throw_AdditionException()
{
// Arrange
await using var context = new GovorDbContext(_options);
var repository = new InvitesRepository(context, _validator);
// Act & Assert
Assert.ThrowsAsync<AdditionException>(async () => await repository.AddAsync(default));
}
[Test]
public async Task Given_NotExistInvitesCode_When_Exist_Then_Returns_False()
{
// Arrange
await using var context = new GovorDbContext(_options);
var repository = new InvitesRepository(context, _validator);
// Act
var result = repository.Exist(Guid.NewGuid());
Assert.That(result, Is.False);
}
[Test]
public async Task Given_ExistInvitesCode_When_Exist_Then_Returns_False()
{
// Arrange
var invitation = _fixture.Create<Invitation>();
invitation.Code = string.Join("", _fixture.CreateMany<char>(12));
invitation.EndDate = invitation.DateCreated.AddHours(1);
await using var context = new GovorDbContext(_options);
var repository = new InvitesRepository(context, _validator);
context.Invitations.Add(invitation);
await context.SaveChangesAsync();
// Act
var result = repository.Exist(invitation.Id);
var result2 = repository.Exist(invitation);
Assert.That(result, Is.True);
Assert.That(result2, Is.True);
}
[Test]
public async Task Given_InvalidInvites_When_Exist_Then_Returns_False()
{
// Arrange
await using var context = new GovorDbContext(_options);
var repository = new InvitesRepository(context, _validator);
// Act & Assert
Assert.Throws<InvalidObjectException<Invitation>>(() => repository.Exist(default(Invitation)));
}
}
@@ -89,4 +89,16 @@ public class InvitationValidatorTests
Assert.Throws<InvalidObjectException<Invitation>>( () => _messageValidator.Validate(invitation));
Assert.That(_messageValidator.TryValidate(invitation), Is.False);
}
[Test]
public void Given_InvalidCode_When_Exist_Then_Returns_False()
{
// Arrange
var invitation = _fixture.Create<Invitation>();
invitation.Code = string.Empty;
// Act & Assert
Assert.Throws<InvalidObjectException<Invitation>>( () => _messageValidator.Validate(invitation));
Assert.That(_messageValidator.TryValidate(invitation), Is.False);
}
}
@@ -38,7 +38,7 @@ public class AuthService : IAccountService
throw new UserAlreadyExistException(name);
// 2. Проверка валидности инвайта
var invite = await _invitesRepository.GetByCodeAsync(inviteCode);
var invite = await _invitesRepository.FindByCodeAsync(inviteCode);
// 3. Генерация пароля
var passwordHash = _passwordHasher.Hash(password);
@@ -22,7 +22,7 @@ public class JwtService : IJwtService
public string GenerateJwtToken(User user)
{
var invite = _invitesRepository.GetByIdAsync(user.InviteId).Result;
var invite = _invitesRepository.FindByIdAsync(user.InviteId).Result;
var claims = new[]
{
+2 -1
View File
@@ -1,5 +1,6 @@
using System.ComponentModel.DataAnnotations;
using Govor.Core.Infrastructure.Validators;
using Govor.Core.Models;
namespace Govor.Core.DTOs;
@@ -13,6 +14,6 @@ public record RegistrationDto
[Required]
[MinLength(8)]
public string Password { get; init; }
[MinLength(8)]
[MinLength(InvitationValidator.MIN_INVITATION_LENGTH)]
public string InviteLink { get; init; }
}
@@ -4,6 +4,7 @@ namespace Govor.Core.Infrastructure.Validators;
public class InvitationValidator : IObjectValidator<Invitation>
{
public const int MIN_INVITATION_LENGTH = 10;
public void Validate(Invitation inv)
{
try
@@ -18,6 +19,8 @@ public class InvitationValidator : IObjectValidator<Invitation>
throw new ArgumentException("EndDate cannot be less than StartDate", nameof(inv.EndDate));
if(inv.MaxParticipants <= 0)
throw new ArgumentException("MaxParticipants cannot be less than 0", nameof(inv.MaxParticipants));
if(inv.Code == string.Empty || inv.Code.Length < MIN_INVITATION_LENGTH)
throw new ArgumentException($"Code cannot be empty or less then {MIN_INVITATION_LENGTH}", nameof(inv.Code));
}
catch (Exception ex)
{
+13
View File
@@ -4,9 +4,22 @@ public class Invitation
{
public Guid Id { get; set; }
public bool IsAdmin { get; set; }
public string Code { get; set; }
public string Description { get; set; }
public DateTime DateCreated { get; set; }
public DateTime EndDate { get; set; }
public int MaxParticipants { get; set; }
public List<User> Users { get; set; } = new List<User>();
public override bool Equals(object? obj)
{
var invitation = obj as Invitation ?? throw new InvalidCastException();
return Id == invitation.Id &&
IsAdmin == invitation.IsAdmin &&
Description == invitation.Description &&
DateCreated == invitation.DateCreated &&
EndDate == invitation.EndDate &&
MaxParticipants == invitation.MaxParticipants;
}
}
@@ -6,5 +6,5 @@ public interface IAdminsWriter
{
Task AddAsync(Admin admin);
Task UpdateAsync(Admin admin);
Task DeleteAsync(Guid admin);
Task RemoveAsync(Guid admin);
}
@@ -5,7 +5,7 @@ namespace Govor.Core.Repositories.Invaites;
public interface IInvitesReader
{
Task<List<Invitation>> GetAllAsync();
Task<Invitation> GetByIdAsync(Guid id);
Task<Invitation> GetByCodeAsync(string code);
Task<List<Invitation>> GetAdminsInvitesAsync();
Task<Invitation> FindByIdAsync(Guid id);
Task<Invitation> FindByCodeAsync(string code);
Task<List<Invitation>> FindAdminsInvitesAsync();
}
+1 -1
View File
@@ -72,7 +72,7 @@ public class AdminsRepository(GovorDbContext context, IObjectValidator<Admin> va
}
}
public async Task DeleteAsync(Guid admin)
public async Task RemoveAsync(Guid admin)
{
try
{
+96 -15
View File
@@ -1,6 +1,9 @@
using Govor.Core.Infrastructure.Extensions;
using Govor.Core.Infrastructure.Validators;
using Govor.Core.Models;
using Govor.Core.Repositories.Invaites;
using Govor.Data.Repositories.Exceptions;
using Microsoft.EntityFrameworkCore;
namespace Govor.Data.Repositories;
@@ -17,46 +20,124 @@ public class InvitesRepository : IInvitesRepository
public async Task<List<Invitation>> GetAllAsync()
{
throw new NotImplementedException();
return await _context.Invitations
.AsNoTracking()
.Include(i => i.Users)
.ToListOrThrowIfEmpty(new NotFoundException("Database is empty"));
}
public Task<Invitation> GetByIdAsync(Guid id)
public async Task<Invitation> FindByIdAsync(Guid id)
{
throw new NotImplementedException();
return await _context.Invitations
.AsNoTracking()
.Include(i => i.Users)
.FirstOrDefaultAsync(i => i.Id == id)
?? throw new NotFoundByKeyException<Guid>(id, "Invitation with given id does not exist");
}
public Task<Invitation> GetByCodeAsync(string code)
public async Task<Invitation> FindByCodeAsync(string code)
{
throw new NotImplementedException();
return await _context.Invitations
.AsNoTracking()
.Include(i => i.Users)
.FirstOrDefaultAsync(i => i.Code == code)
?? throw new NotFoundByKeyException<string>(code, "Invitation with given code does not exist");
}
public Task<List<Invitation>> GetAdminsInvitesAsync()
public async Task<List<Invitation>> FindAdminsInvitesAsync()
{
throw new NotImplementedException();
return await _context.Invitations
.AsNoTracking()
.Include(i => i.Users)
.Where(i => i.IsAdmin)
.ToListOrThrowIfEmpty(new NotFoundByKeyException<bool>(true, "Admins invites do not exist"));
}
public Task AddAsync(Invitation invitation)
public async Task AddAsync(Invitation invitation)
{
throw new NotImplementedException();
try
{
_validator.Validate(invitation);
_context.Invitations.Add(invitation);
await _context.SaveChangesAsync();
}
catch (InvalidObjectException<Admin> ex)
{
throw new AdditionException("Invitation with given data invalid", ex);
}
catch (Exception ex)
{
throw new AdditionException("Cannot add invitation", ex);
};
}
public Task UpdateAsync(Invitation invitation)
public async Task UpdateAsync(Invitation invitation)
{
throw new NotImplementedException();
try
{
_validator.Validate(invitation);
var rowsAffected = await _context.Invitations
.Where(a => a.Id == invitation.Id)
.ExecuteUpdateAsync(u => u
.SetProperty(i => i.IsAdmin, invitation.IsAdmin)
.SetProperty(i => i.Code, invitation.Code)
.SetProperty(i => i.Description, invitation.Description)
.SetProperty(i => i.DateCreated, invitation.DateCreated)
.SetProperty(i => i.EndDate, invitation.EndDate)
.SetProperty(i => i.MaxParticipants, invitation.MaxParticipants)
.SetProperty(i => i.Users, invitation.Users)
);
if (rowsAffected == 0)
throw new NotFoundByKeyException<Guid>(invitation.Id, "Invitation with given data invalid");
}
catch (NotFoundByKeyException<Guid> ex)
{
throw new UpdateException($"Not found invitation by given id {invitation.Id}", ex);
}
catch (Exception ex)
{
throw new UpdateException($"Error when updating the invitation {invitation.Id}", ex);
}
}
public Task RemoveAsync(Invitation invitation)
public async Task RemoveAsync(Invitation invitation)
{
throw new NotImplementedException();
try
{
var result = await FindByIdAsync(invitation.Id);
_context.Invitations.Remove(result);
await _context.SaveChangesAsync();
}
catch (NotFoundByKeyException<Guid> ex)
{
throw new RemoveException($"Not found invitation by given id {invitation.Id}", ex);
}
catch (Exception ex)
{
throw new RemoveException("Error when removing the invitation", ex);
}
}
public bool Exist(Invitation invitation)
{
throw new NotImplementedException();
_validator.Validate(invitation);
return _context.Invitations.Any(i => i.Id == invitation.Id &&
i.Code == invitation.Code &&
i.IsAdmin == invitation.IsAdmin &&
i.DateCreated == invitation.DateCreated &&
i.EndDate == invitation.EndDate &&
i.Description == invitation.Description &&
i.MaxParticipants == invitation.MaxParticipants
);
}
public bool Exist(Guid guid)
{
throw new NotImplementedException();
return _context.Invitations.Any(i => i.Id == guid);
}
}