Refactors and enhances tests#68
Conversation
Refactors the test suite by reorganizing and renaming test projects to improve clarity and maintainability. Also, integrates Testcontainers for more robust integration tests, ensuring reliable database interactions and adds Docker layer caching in CI to speed up workflow execution.
WalkthroughReestrutura a solução e testes, adiciona testes de integração com PostgreSQL via Testcontainers, implementa migration EF Core com seed, adiciona operações bulk ao repositório, refatora UnitOfWork para transações EF Core com tratamento de cancelamento e move/renomeia muitos namespaces e ativos de testes. Changes
Sequence Diagram(s)sequenceDiagram
participant Caller as Chamador
participant UoW as UnitOfWork
participant DbCtx as DbContext
participant Tx as IDbContextTransaction
participant Logger as ILogger
Note over Caller,UoW: SaveChangesAsync (fluxo refatorado)
Caller->>UoW: SaveChangesAsync(cancellationToken)
UoW->>DbCtx: Database.OpenConnectionAsync()
UoW->>DbCtx: Database.BeginTransactionAsync()
activate Tx
alt sucesso
UoW->>DbCtx: _dbContext.SaveChangesAsync(cancellationToken)
UoW->>Tx: CommitAsync()
else cancelado
UoW->>Logger: LogWarning("Operation canceled: ...")
UoW->>Tx: RollbackAsync(CancellationToken.None)
UoW-->>Caller: throw OperationCanceledException
else erro
UoW->>Logger: LogError("Save failed: ...")
UoW->>Tx: RollbackAsync(CancellationToken.None)
UoW-->>Caller: rethrow
end
UoW->>DbCtx: Database.CloseConnection()
deactivate Tx
UoW-->>Caller: retorna/propaga resultado
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Possibly related PRs
Suggested labels
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 11
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
InvoiceReminder.UnitTests.Infrastructure/Authentication/StringHashExtensionTests.cs (1)
42-50: Remova o métodoToMD5()não utilizado do código de produção.O método
ToMD5()está definido emStringHashExtension.cs, mas não é utilizado em nenhum lugar do código de produção. Visto que MD5 é criptograficamente quebrado desde 1996 e não deve ser usado para fins de segurança, recomenda-se remover completamente esse método para reduzir a superfície de ataque em uma área sensível (namespaceAuthentication). Alternativas seguras comoToSHA256()eToSHA512()já estão disponíveis na mesma classe e devem ser utilizadas.InvoiceReminder.UnitTests.Infrastructure/Data/Repository/InvoiceRepositoryTests.cs (1)
20-22: String de conexão nula causará falhas.O uso de
UseNpgsql(default)passanullcomo string de conexão, o que causará exceções em tempo de execução quando o DbContext tentar se conectar ou executar operações. Para testes unitários que simulam o DbContext, considere:
- Usar um banco de dados em memória (SQLite in-memory ou EF Core In-Memory provider)
- Mockar completamente o DbContext e DbSets sem configurar providers de banco de dados reais
- Mover esses testes para o projeto de testes de integração com Testcontainers PostgreSQL
🔎 Sugestão: Usar SQLite in-memory para testes unitários
- var options = new DbContextOptionsBuilder<CoreDbContext>() - .UseNpgsql(default) - .Options; + var options = new DbContextOptionsBuilder<CoreDbContext>() + .UseSqlite("DataSource=:memory:") + .Options; - - _dbContext = Substitute.ForPartsOf<CoreDbContext>(options); + + _dbContext = new CoreDbContext(options); + _dbContext.Database.OpenConnection(); + _dbContext.Database.EnsureCreated();InvoiceReminder.UnitTests.API/AuthenticationSetup/BearerSecuritySchemeTransformerTests.cs (1)
45-55: Verificação incompleta no assertion.Na linha 51,
ContainsKey("Bearer")é chamado mas seu resultado não é verificado. A expressão retornaboolmas é descartada.🔎 Correção sugerida
_ = _document.Components.SecuritySchemes.ShouldNotBeNull(); - _ = _document.Components.SecuritySchemes.ContainsKey("Bearer"); + _document.Components.SecuritySchemes.ContainsKey("Bearer").ShouldBeTrue(); _document.Components.SecuritySchemes["Bearer"].Scheme.ShouldBeEquivalentTo("bearer");
♻️ Duplicate comments (1)
InvoiceReminder.IntegrationTests/Data/Repository/BaseRepositoryIntegrationTests.cs (1)
47-55: Duplicação de UserFaker detectada.O método
UserFaker()está duplicado em múltiplos arquivos de teste. Conforme sugerido na revisão deUserRepositoryIntegrationTests.cs, considere extrair para uma classe auxiliar compartilhada.
🧹 Nitpick comments (22)
InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/InvoiceConfigTests.cs (1)
9-17: Considere aprimorar a cobertura do teste.O teste atual apenas verifica que o construtor de
InvoiceConfignão lança exceção, mas não valida se a configuração do Entity Framework está correta. Considere adicionar testes que usem umModelBuildermock para verificar que as configurações de entidade (chaves primárias, relacionamentos, constraints, etc.) estão sendo aplicadas corretamente.💡 Exemplo de teste mais abrangente
+using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Conventions; + [TestMethod] public void InvoiceConfig_ShouldNotThrowErrorWhenInstantiated() { // Arrange && Act Action action = () => _ = new InvoiceConfig(); // Assert action.ShouldNotThrow(); } + +[TestMethod] +public void InvoiceConfig_ShouldConfigureEntityCorrectly() +{ + // Arrange + var builder = new ModelBuilder(new ConventionSet()); + var config = new InvoiceConfig(); + + // Act + config.Configure(builder.Entity<Invoice>()); + + // Assert + var entityType = builder.Model.FindEntityType(typeof(Invoice)); + entityType.ShouldNotBeNull(); + // Adicione asserções específicas para verificar chaves, relacionamentos, etc. +}InvoiceReminder.UnitTests.Infrastructure/Data/Repository/EmailAuthTokenRepositoryTests.cs (2)
20-26: Configuração do DbContext com string de conexão nula.A linha 21 usa
UseNpgsql(default), que passanullcomo string de conexão. Embora isso funcione para este teste específico de atribuibilidade de tipos, é uma abordagem incomum que pode causar confusão.Adicionalmente, o uso de
Substitute.ForPartsOf<CoreDbContext>para criar um substituto parcial de um DbContext é atípico e pode não ser necessário para um teste que apenas verifica relações de tipos.
28-44: Considere se este teste adiciona valor suficiente.Este teste apenas verifica atribuibilidade de tipos, que é algo que o compilador já garante em tempo de compilação. Como os objetivos da PR mencionam "removendo testes unitários da camada de infraestrutura em favor de testes de integração", e já existem testes de integração que cobrem a funcionalidade real do
EmailAuthTokenRepository, considere se este teste unitário é realmente necessário.Testes de atribuibilidade de tipos geralmente agregam pouco valor, pois não verificam comportamento real e não podem falhar sem que o código também falhe na compilação.
💡 Alternativa: remover este teste e confiar nos testes de integração existentes
Como já existem testes de integração que cobrem cenários reais (GetByIdAsync, GetByUserIdAsync, etc.), você pode considerar remover este arquivo de teste unitário completamente, alinhando-se melhor com os objetivos da PR de mover testes de infraestrutura para testes de integração.
InvoiceReminder.UnitTests.JobScheduler/JobSettings/CronJobTests.cs (2)
62-68: UseReceivedem vez deReceivedWithAnyArgsao especificar matchers de argumentos.O uso de
ReceivedWithAnyArgs(1)com matchers explícitos de argumentos (Arg.Any<EventId>(),Arg.Any<object>(), etc.) é redundante. OReceivedWithAnyArgsfoi projetado para ignorar todos os argumentos, então especificar matchers não tem efeito e cria confusão sobre a intenção do teste.🔎 Refatoração sugerida
- _logger.ReceivedWithAnyArgs(1).Log( + _logger.Received(1).Log( LogLevel.Information, Arg.Any<EventId>(), Arg.Any<object>(), null, Arg.Any<Func<object, Exception, string>>() );Ou, se não precisa verificar os argumentos:
- _logger.ReceivedWithAnyArgs(1).Log( - LogLevel.Information, - Arg.Any<EventId>(), - Arg.Any<object>(), - null, - Arg.Any<Func<object, Exception, string>>() - ); + _logger.ReceivedWithAnyArgs(1).Log<object>();
110-116: Uso correto deReceivedcom matchers específicos, mas note a inconsistência.A mudança para
Received(1).Log(...)com matchers específicos está correta, especialmente a verificação de que o estado contém "Test Job Description triggered..." na linha 113. No entanto, isso cria uma inconsistência com o teste emExecute_ShouldCreateScopeResolveServiceAndSendMessage(linhas 62-68) que ainda usaReceivedWithAnyArgs. Considere padronizar a abordagem de asserção do logger em todos os testes.InvoiceReminder.UnitTests.JobScheduler/HostedService/QuartzHostedServiceTests.cs (1)
163-169: Considere verificar o conteúdo da mensagem para maior consistência.As asserções de logging nestas linhas usam
Arg.Any<object>()para o parâmetro de estado, enquanto a asserção nas linhas 91-97 verifica o conteúdo da mensagem comArg.Is<object>(o => o.ToString().Contains("CronJob inválido:")).Verificar o conteúdo da mensagem tornaria os testes mais específicos e ajudaria a detectar regressões nas mensagens de erro.
🔎 Refatoração sugerida para maior especificidade
Para as linhas 163-169:
_logger.Received(2).Log( LogLevel.Error, Arg.Any<EventId>(), - Arg.Any<object>(), + Arg.Is<object>(o => o.ToString().Contains("CronJob inválido:")), Arg.Any<Exception>(), Arg.Any<Func<object, Exception, string>>() );Para as linhas 195-201:
_logger.Received(1).Log( LogLevel.Error, Arg.Any<EventId>(), - Arg.Any<object>(), + Arg.Is<object>(o => o.ToString().Contains("CronJob inválido:")), Arg.Any<Exception>(), Arg.Any<Func<object, Exception, string>>() );Also applies to: 195-201
InvoiceReminder.UnitTests.Infrastructure/Data/Repository/JobScheduleRepositoryTests.cs (2)
20-22: Considere usar uma connection string fictícia ao invés dedefault.Passar
default(null) como connection string paraUseNpgsqlnão causa problemas aqui porque oDbContexté substituído na linha 24, mas pode ser confuso para futuros mantenedores.🔎 Sugestão de melhoria
var options = new DbContextOptionsBuilder<CoreDbContext>() - .UseNpgsql(default) + .UseNpgsql("Host=localhost;Database=test;Username=test;Password=test") .Options;
12-44: Considere consolidar ou remover este arquivo de teste.Após a remoção dos testes comportamentais (que foram movidos para testes de integração), esta classe contém apenas um teste de atribuibilidade de tipos. A infraestrutura de setup (constructor com mocks) parece super-dimensionada para um único teste que apenas instancia o repositório.
Considere:
- Remover este arquivo completamente se o teste de tipo não agrega valor significativo
- Consolidar o teste de tipo em um arquivo de testes de tipo centralizado
- Simplificar o constructor se optar por manter o arquivo
InvoiceReminder.UnitTests.Infrastructure/Data/Repository/ScanEmailDefinitionRepositoryTests.cs (1)
28-44: Teste valida apenas estrutura, não comportamento.Este teste verifica apenas a compatibilidade de tipos e implementação de interfaces, mas não testa nenhum comportamento real do repositório (operações CRUD, queries, etc.).
Considerações:
- Verificações de tipo são garantias em tempo de compilação - se o código compila, essas asserções sempre passarão
- O valor deste teste é mínimo para garantir qualidade
- Dado que o PR está migrando para testes de integração com Testcontainers, um teste de integração seria mais valioso
Sugestão: Substitua este teste por testes de integração que validem o comportamento real do repositório, como:
- Adicionar uma ScanEmailDefinition e verificar se foi persistida
- Buscar por ID e validar os dados retornados
- Atualizar e deletar registros
Isso se alinha melhor com os objetivos do PR de adicionar "testes de integração mais robustos" com Testcontainers.
InvoiceReminder.UnitTests.Infrastructure/Data/Repository/InvoiceRepositoryTests.cs (1)
28-44: Testes comportamentais foram movidos para o projeto de integração — adição de comentário esclarecedor recomendada.Os testes comportamentais (
AddAsync,BulkInsertAsync,Remove,GetById,GetAll,Update,Where,Dispose) estão confirmados emBaseRepositoryIntegrationTests.cseInvoiceRepositoryIntegrationTests.cscom Testcontainers, seguindo a estrutura adequada de separação entre testes unitários e de integração.No entanto, o teste unitário atual é puramente de atribuibilidade de tipos, o que oferece cobertura limitada. Considere adicionar um comentário no arquivo explicando que os testes de comportamento estão no projeto de integração, ou adicionar alguns testes unitários de
InvoiceRepositorycom mocks completos para cenários específicos que não requerem banco de dados (ex.: validações de entrada, tratamento de exceções).InvoiceReminder.UnitTests.Infrastructure/Data/Repository/UserRepositoryTests.cs (1)
28-44: Teste de conformidade de tipo aprovado, com sugestão de melhoria opcional.O teste valida corretamente que
UserRepositoryimplementa as interfaces esperadas e herda deBaseRepository<CoreDbContext, User>. O uso deUseNpgsql(default)é aceitável neste contexto, pois o teste não acessa o banco de dados.No entanto, este teste unitário cobre apenas a conformidade estrutural. Embora os testes de integração no arquivo
UserRepositoryIntegrationTests.cscubram o comportamento real, considere adicionar testes unitários para validar lógica específica do repositório (se houver) usando mocks completos do DbContext.InvoiceReminder.Data/Migrations/20250930210104_Initial_Create.cs (2)
8-10: Posição do comentário XML não-convencional.O comentário de documentação XML
/// <inheritdoc />está posicionado após o atributo[ExcludeFromCodeCoverage]. Por convenção, comentários de documentação devem preceder todos os atributos.🔎 Correção sugerida
[ExcludeFromCodeCoverage] -/// <inheritdoc /> +/// <inheritdoc /> public partial class Initial_Create : MigrationOu, de preferência:
+/// <inheritdoc /> [ExcludeFromCodeCoverage] -/// <inheritdoc /> public partial class Initial_Create : Migration
15-18: Criação de schema redundante.A criação do schema é feita duas vezes: primeiro com SQL direto (
CREATE SCHEMA IF NOT EXISTS) e depois comEnsureSchema. Embora seja seguro (ambos são idempotentes), é desnecessário.🔎 Sugestão de simplificação
- _ = migrationBuilder.Sql("CREATE SCHEMA IF NOT EXISTS invoice_reminder;"); - _ = migrationBuilder.EnsureSchema( name: "invoice_reminder");InvoiceReminder.Data/Repository/UnitOfWork.cs (1)
63-63: UsarcancellationTokencancelado noRollbackAsyncpode falhar.Se a exceção original foi causada por uma requisição de cancelamento (mas não capturada pelo
whenclause), passar o mesmocancellationTokenparaRollbackAsyncpode impedir o rollback. Considere usarCancellationToken.Nonepara garantir que o rollback seja executado.🔎 Correção proposta
- await transaction.RollbackAsync(cancellationToken); + await transaction.RollbackAsync(CancellationToken.None);InvoiceReminder.IntegrationTests/Data/ContainerSetup/DatabaseFixture.cs (1)
15-28: Considere adicionar tratamento de erro para falha na inicialização do container.Se
StartAsyncouRunMigrationsfalhar, o erro pode não ser claro para depuração. Considere adicionar logs ou mensagens de erro mais descritivas.🔎 Sugestão
[AssemblyInitialize] public static async Task AssemblyInit(TestContext context) { - _dbContainer = new PostgreSqlBuilder() - .WithDatabase("postgres") - .WithUsername("postgres") - .WithPassword("Fake!Password#123") - .WithImage("postgres:15-alpine") - .Build(); - - await _dbContainer.StartAsync(context.CancellationToken); - await CreateSchema(context); - await RunMigrations(context); + try + { + _dbContainer = new PostgreSqlBuilder() + .WithDatabase("postgres") + .WithUsername("postgres") + .WithPassword("Fake!Password#123") + .WithImage("postgres:15-alpine") + .Build(); + + await _dbContainer.StartAsync(context.CancellationToken); + await CreateSchema(context); + await RunMigrations(context); + } + catch (Exception ex) + { + context.WriteLine($"Failed to initialize test database: {ex.Message}"); + throw; + } }InvoiceReminder.IntegrationTests/Data/Repository/ScanEmailDefinitionRepositoryIntegrationTests.cs (1)
16-37: Considere implementarIDisposableou usar[TestCleanup]para liberar recursos.A classe cria
CoreDbContexteUnitOfWorkno construtor, mas não implementaIDisposablenem usa[TestCleanup]. Isso pode causar vazamento de conexões de banco de dados entre testes. Compare comUnitOfWorkIntegrationTestsque implementaTestInitializeeTestCleanup.🔎 Sugestão
[TestClass] public sealed class ScanEmailDefinitionRepositoryIntegrationTests { - private readonly CoreDbContext _dbContext; - private readonly ILogger<ScanEmailDefinitionRepository> _repositoryLogger; - private readonly ILogger<UnitOfWork> _unitOfWorkLogger; - private readonly ScanEmailDefinitionRepository _repository; - private readonly UnitOfWork _unitOfWork; + private CoreDbContext _dbContext; + private ILogger<ScanEmailDefinitionRepository> _repositoryLogger; + private ILogger<UnitOfWork> _unitOfWorkLogger; + private ScanEmailDefinitionRepository _repository; + private UnitOfWork _unitOfWork; public TestContext TestContext { get; set; } - public ScanEmailDefinitionRepositoryIntegrationTests() + [TestInitialize] + public void TestInitialize() { var options = new DbContextOptionsBuilder<CoreDbContext>() .UseNpgsql(DatabaseFixture.ConnectionString) .Options; _dbContext = new CoreDbContext(options); - _repositoryLogger = Substitute.For<ILogger<ScanEmailDefinitionRepository>>(); ; + _repositoryLogger = Substitute.For<ILogger<ScanEmailDefinitionRepository>>(); _unitOfWorkLogger = Substitute.For<ILogger<UnitOfWork>>(); _repository = new ScanEmailDefinitionRepository(_dbContext, _repositoryLogger); _unitOfWork = new UnitOfWork(_dbContext, _unitOfWorkLogger); } + + [TestCleanup] + public void TestCleanup() + { + _unitOfWork?.Dispose(); + _dbContext?.Dispose(); + }InvoiceReminder.IntegrationTests/Data/Repository/EmailAuthTokenRepositoryIntegrationTests.cs (1)
15-36: Falta implementação de cleanup de recursos.Assim como em
ScanEmailDefinitionRepositoryIntegrationTests, esta classe cria recursos no construtor mas não os libera. Considere usar[TestInitialize]e[TestCleanup]para consistência comUnitOfWorkIntegrationTests.InvoiceReminder.IntegrationTests/Data/Repository/JobScheduleRepositoryIntegrationTests.cs (1)
15-36: Falta implementação de cleanup de recursos.Mesmo padrão dos outros arquivos de teste. Considere usar
[TestInitialize]e[TestCleanup]para liberarDbContexteUnitOfWorkapós cada teste.InvoiceReminder.IntegrationTests/Data/Repository/InvoiceRepositoryIntegrationTests.cs (1)
15-36: Falta implementação de cleanup de recursos.Mesmo padrão dos outros arquivos de teste de integração. Considere padronizar usando
[TestInitialize]e[TestCleanup].InvoiceReminder.IntegrationTests/Data/Repository/UserRepositoryIntegrationTests.cs (2)
40-82: Considere extrair Fakers duplicados para uma classe compartilhada.Os métodos
UserFaker(),EmailAuthTokenFaker()eInvoiceFaker()estão duplicados em múltiplos arquivos de teste (EmailAuthTokenRepositoryIntegrationTests, InvoiceRepositoryIntegrationTests, BaseRepositoryIntegrationTests). Extrair essas definições para uma classe auxiliar compartilhada melhoraria a manutenibilidade.💡 Sugestão: criar classe TestDataFakers
Crie um arquivo
TestDataFakers.cs:namespace InvoiceReminder.IntegrationTests.Data.TestHelpers; public static class TestDataFakers { public static Faker<User> UserFaker() => new Faker<User>() .RuleFor(u => u.Id, _ => Guid.NewGuid()) .RuleFor(u => u.TelegramChatId, f => f.Random.Long(100000000, long.MaxValue)) .RuleFor(u => u.Name, f => f.Person.FullName) .RuleFor(u => u.Email, f => f.Internet.Email()) .RuleFor(u => u.Password, f => f.Internet.Password(length: 16, memorable: false)); public static Faker<EmailAuthToken> EmailAuthTokenFaker() => new Faker<EmailAuthToken>() .RuleFor(e => e.Id, faker => faker.Random.Guid()) // ... demais regras public static Faker<Invoice> InvoiceFaker() => new Faker<Invoice>() .RuleFor(i => i.Id, faker => faker.Random.Guid()) // ... demais regras }Em seguida, use
TestDataFakers.UserFaker()nos arquivos de teste.
295-341: Testes de cancelamento bem implementados, com pequena ineficiência.Os testes verificam corretamente:
- Lançamento de
OperationCanceledException- Logging de warning quando operação é cancelada
Observação menor: As linhas 299 e 323 criam e salvam usuários que não são utilizados nos testes de cancelamento. Isso adiciona overhead desnecessário.
💡 Otimização opcional
[TestMethod] public async Task GetByIdAsync_Should_Handle_Cancellation_Request() { // Arrange - var user = await CreateAndSaveUserAsync(); using var cts = new CancellationTokenSource(); await cts.CancelAsync(); _ = _repositoryLogger.IsEnabled(Arg.Any<LogLevel>()).Returns(true); // Act & Assert _ = await Should.ThrowAsync<OperationCanceledException>( - async () => await _repository.GetByIdAsync(user.Id, cts.Token) + async () => await _repository.GetByIdAsync(Guid.NewGuid(), cts.Token) );Mesma otimização pode ser aplicada ao teste
GetByEmailAsync_Should_Handle_Cancellation_Request.InvoiceReminder.IntegrationTests/Data/Repository/BaseRepositoryIntegrationTests.cs (1)
246-320: Testes de GetAll bem implementados, com oportunidade de melhoria.Os testes verificam adequadamente:
- Recuperação de todas as entidades
- Comportamento NoTracking (estado
Detachedna linha 301)- Coleção vazia quando não há entidades
Observação: O padrão de descartar e recriar o contexto (linhas 254-263, 285-293, 308-312) é repetido. Considere extrair para um método auxiliar.
💡 Sugestão de helper method
private BaseRepository<CoreDbContext, T> CreateFreshRepository<T>() where T : class { var options = new DbContextOptionsBuilder<CoreDbContext>() .UseNpgsql(DatabaseFixture.ConnectionString) .Options; var dbContext = new CoreDbContext(options); return new BaseRepository<CoreDbContext, T>(dbContext); }Uso:
// Dispose current context _userRepository.Dispose(); await _dbContext.DisposeAsync(); // Use fresh repository using var repository = CreateFreshRepository<User>(); var result = repository.GetAll().ToList();
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (96)
.github/workflows/workflow-ci.ymlDirectory.Packages.propsInvoiceReminder.API/AuthenticationSetup/BearerSecuritySchemeTransformer.csInvoiceReminder.ArchitectureTests/InvoiceReminder.ArchitectureTests.csprojInvoiceReminder.Data/Interfaces/IUserRepository.csInvoiceReminder.Data/Migrations/20250930210104_Initial_Create.csInvoiceReminder.Data/Persistence/EntitiesConfig/EmailAuthTokenConfig.csInvoiceReminder.Data/Persistence/EntitiesConfig/InvoiceConfig.csInvoiceReminder.Data/Persistence/EntitiesConfig/JobScheduleConfig.csInvoiceReminder.Data/Persistence/EntitiesConfig/ScanEmailDefinitionConfig.csInvoiceReminder.Data/Persistence/EntitiesConfig/UserConfig.csInvoiceReminder.Data/Repository/UnitOfWork.csInvoiceReminder.Infrastructure.UnitTests/Data/Repository/BaseRepositoryTests.csInvoiceReminder.Infrastructure.UnitTests/Data/Repository/ScanEmailDefinitionRepositoryTests.csInvoiceReminder.Infrastructure.UnitTests/Data/Repository/UnitOfWorkTests.csInvoiceReminder.Infrastructure.UnitTests/Data/Repository/UserRepositoryTests.csInvoiceReminder.IntegrationTests/Data/ContainerSetup/DatabaseFixture.csInvoiceReminder.IntegrationTests/Data/Repository/BaseRepositoryIntegrationTests.csInvoiceReminder.IntegrationTests/Data/Repository/EmailAuthTokenRepositoryIntegrationTests.csInvoiceReminder.IntegrationTests/Data/Repository/InvoiceRepositoryIntegrationTests.csInvoiceReminder.IntegrationTests/Data/Repository/JobScheduleRepositoryIntegrationTests.csInvoiceReminder.IntegrationTests/Data/Repository/ScanEmailDefinitionRepositoryIntegrationTests.csInvoiceReminder.IntegrationTests/Data/Repository/UnitOfWorkIntegrationTests.csInvoiceReminder.IntegrationTests/Data/Repository/UserRepositoryIntegrationTests.csInvoiceReminder.IntegrationTests/InvoiceReminder.IntegrationTests.csprojInvoiceReminder.IntegrationTests/MSTestSettings.csInvoiceReminder.UnitTests.API/AuthenticationSetup/BearerSecuritySchemeTransformerTests.csInvoiceReminder.UnitTests.API/AuthenticationSetup/JwtBearerOptionsSetupTests.csInvoiceReminder.UnitTests.API/AuthenticationSetup/JwtOptionsSetupTests.csInvoiceReminder.UnitTests.API/AuthenticationSetup/LoginRequestTests.csInvoiceReminder.UnitTests.API/AuthenticationSetup/MockAuthenticationHandler.csInvoiceReminder.UnitTests.API/Endpoints/GoogleOAuthEndpointsTests.csInvoiceReminder.UnitTests.API/Endpoints/InvoiceEndpointsTests.csInvoiceReminder.UnitTests.API/Endpoints/JobScheduleEndPointsTests.csInvoiceReminder.UnitTests.API/Endpoints/LoginEndpointTests.csInvoiceReminder.UnitTests.API/Endpoints/ScanEmailDefinitionEndpointsTests.csInvoiceReminder.UnitTests.API/Endpoints/SendMessageEndpointsTests.csInvoiceReminder.UnitTests.API/Endpoints/UserEndpointsTests.csInvoiceReminder.UnitTests.API/Factories/CustomWebApplicationFactory.csInvoiceReminder.UnitTests.API/InvoiceReminder.UnitTests.API.csprojInvoiceReminder.UnitTests.API/MSTestSettings.csInvoiceReminder.UnitTests.Application/AppServices/BaseAppServiceTests.csInvoiceReminder.UnitTests.Application/AppServices/EmailAuthTokenAppServiceTests.csInvoiceReminder.UnitTests.Application/AppServices/InvoiceAppServiceTests.csInvoiceReminder.UnitTests.Application/AppServices/JobScheduleAppServiceTests.csInvoiceReminder.UnitTests.Application/AppServices/ScanEmailDefinitionAppServiceTests.csInvoiceReminder.UnitTests.Application/AppServices/UserAppServiceTests.csInvoiceReminder.UnitTests.Application/InvoiceReminder.UnitTests.Application.csprojInvoiceReminder.UnitTests.Application/MSTestSettings.csInvoiceReminder.UnitTests.Application/ViewModels/EmailAuthTokenViewModelTests.csInvoiceReminder.UnitTests.Application/ViewModels/InvoiceViewModelTests.csInvoiceReminder.UnitTests.Application/ViewModels/JobScheduleViewmodelTests.csInvoiceReminder.UnitTests.Application/ViewModels/ScanEmailDefinitionViewModelTests.csInvoiceReminder.UnitTests.Application/ViewModels/UserViewModelTests.csInvoiceReminder.UnitTests.Domain/Entities/EmailAuthTokenTests.csInvoiceReminder.UnitTests.Domain/Entities/InvoiceTests.csInvoiceReminder.UnitTests.Domain/Entities/JobScheduleTests.csInvoiceReminder.UnitTests.Domain/Entities/ScanEmailDefinitionTests.csInvoiceReminder.UnitTests.Domain/Entities/UserTests.csInvoiceReminder.UnitTests.Domain/Extensions/EntityExtensionsTests.csInvoiceReminder.UnitTests.Domain/Extensions/UserExtensionsTests.csInvoiceReminder.UnitTests.Domain/Extensions/UserParameterTests.csInvoiceReminder.UnitTests.Domain/InvoiceReminder.UnitTests.Domain.csprojInvoiceReminder.UnitTests.Domain/MSTestSettings.csInvoiceReminder.UnitTests.Domain/Services/Configuration/ConfigurationServiceTests.csInvoiceReminder.UnitTests.Domain/Services/Configuration/TokenCryptoServiceTests.csInvoiceReminder.UnitTests.ExternalServices/BarcodeReader/BarcodeReaderServiceTests.csInvoiceReminder.UnitTests.ExternalServices/InvoiceReminder.UnitTests.ExternalServices.csprojInvoiceReminder.UnitTests.ExternalServices/MSTestSettings.csInvoiceReminder.UnitTests.ExternalServices/SendMessage/SendMessageServiceTests.csInvoiceReminder.UnitTests.Infrastructure/Authentication/JwtObjectTests.csInvoiceReminder.UnitTests.Infrastructure/Authentication/JwtOptionsTests.csInvoiceReminder.UnitTests.Infrastructure/Authentication/JwtProviderTests.csInvoiceReminder.UnitTests.Infrastructure/Authentication/StringHashExtensionTests.csInvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/InvoiceConfigTests.csInvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/JobScheduleConfigTests.csInvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/ScanEmailDefinitionConfigTests.csInvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/UserConfigTests.csInvoiceReminder.UnitTests.Infrastructure/Data/Repository/EmailAuthTokenRepositoryTests.csInvoiceReminder.UnitTests.Infrastructure/Data/Repository/InvoiceRepositoryTests.csInvoiceReminder.UnitTests.Infrastructure/Data/Repository/JobScheduleRepositoryTests.csInvoiceReminder.UnitTests.Infrastructure/Data/Repository/ScanEmailDefinitionRepositoryTests.csInvoiceReminder.UnitTests.Infrastructure/Data/Repository/UserRepositoryTests.csInvoiceReminder.UnitTests.Infrastructure/InvoiceReminder.UnitTests.Infrastructure.csprojInvoiceReminder.UnitTests.Infrastructure/MSTestSettings.csInvoiceReminder.UnitTests.JobScheduler/HostedService/QuartzHostedServiceTests.csInvoiceReminder.UnitTests.JobScheduler/InvoiceReminder.UnitTests.JobScheduler.csprojInvoiceReminder.UnitTests.JobScheduler/JobSettings/CronJobTests.csInvoiceReminder.UnitTests.JobScheduler/MSTestSettings.csInvoiceReminder.UnitTests.SUT.Assets/Exception/PropertyTestException.csInvoiceReminder.UnitTests.SUT.Assets/Helpers/Guard.csInvoiceReminder.UnitTests.SUT.Assets/Helpers/TypeFactory.csInvoiceReminder.UnitTests.SUT.Assets/InvoiceReminder.UnitTests.SUT.Assets.csprojInvoiceReminder.UnitTests.SUT.Assets/PropertyTester.csInvoiceReminder.slnglobal.json
💤 Files with no reviewable changes (6)
- InvoiceReminder.Infrastructure.UnitTests/Data/Repository/UnitOfWorkTests.cs
- InvoiceReminder.Data/Interfaces/IUserRepository.cs
- InvoiceReminder.Infrastructure.UnitTests/Data/Repository/ScanEmailDefinitionRepositoryTests.cs
- InvoiceReminder.ArchitectureTests/InvoiceReminder.ArchitectureTests.csproj
- InvoiceReminder.Infrastructure.UnitTests/Data/Repository/BaseRepositoryTests.cs
- InvoiceReminder.Infrastructure.UnitTests/Data/Repository/UserRepositoryTests.cs
🧰 Additional context used
🧬 Code graph analysis (8)
InvoiceReminder.UnitTests.Infrastructure/Data/Repository/EmailAuthTokenRepositoryTests.cs (1)
InvoiceReminder.Domain/Entities/EmailAuthToken.cs (1)
EmailAuthToken(3-12)
InvoiceReminder.IntegrationTests/Data/Repository/ScanEmailDefinitionRepositoryIntegrationTests.cs (2)
InvoiceReminder.Data/Repository/UnitOfWork.cs (6)
UnitOfWork(12-113)UnitOfWork(20-25)UnitOfWork(109-112)Task(27-72)Task(74-80)Task(82-88)InvoiceReminder.Domain/Entities/ScanEmailDefinition.cs (1)
ScanEmailDefinition(5-13)
InvoiceReminder.Data/Repository/UnitOfWork.cs (1)
InvoiceReminder.Data/Repository/BaseRepository.cs (2)
Dispose(79-87)Dispose(89-93)
InvoiceReminder.UnitTests.Infrastructure/Data/Repository/ScanEmailDefinitionRepositoryTests.cs (1)
InvoiceReminder.Domain/Entities/ScanEmailDefinition.cs (1)
ScanEmailDefinition(5-13)
InvoiceReminder.IntegrationTests/Data/Repository/UserRepositoryIntegrationTests.cs (3)
InvoiceReminder.IntegrationTests/Data/Repository/BaseRepositoryIntegrationTests.cs (1)
Faker(47-55)InvoiceReminder.IntegrationTests/Data/Repository/EmailAuthTokenRepositoryIntegrationTests.cs (2)
Faker(40-48)Faker(50-62)InvoiceReminder.IntegrationTests/Data/Repository/InvoiceRepositoryIntegrationTests.cs (2)
Faker(40-48)Faker(50-70)
InvoiceReminder.IntegrationTests/Data/Repository/InvoiceRepositoryIntegrationTests.cs (2)
InvoiceReminder.IntegrationTests/Data/ContainerSetup/DatabaseFixture.cs (2)
Task(36-43)Task(45-54)InvoiceReminder.Data/Repository/UnitOfWork.cs (6)
UnitOfWork(12-113)UnitOfWork(20-25)UnitOfWork(109-112)Task(27-72)Task(74-80)Task(82-88)
InvoiceReminder.IntegrationTests/Data/Repository/EmailAuthTokenRepositoryIntegrationTests.cs (3)
InvoiceReminder.Data/Repository/UnitOfWork.cs (6)
UnitOfWork(12-113)UnitOfWork(20-25)UnitOfWork(109-112)Task(27-72)Task(74-80)Task(82-88)InvoiceReminder.Domain/Extensions/EntityExtensions.cs (1)
Guid(41-52)InvoiceReminder.Domain/Entities/EmailAuthToken.cs (1)
EmailAuthToken(3-12)
InvoiceReminder.IntegrationTests/Data/Repository/UnitOfWorkIntegrationTests.cs (1)
InvoiceReminder.Data/Repository/UnitOfWork.cs (8)
UnitOfWork(12-113)UnitOfWork(20-25)UnitOfWork(109-112)Dispose(90-101)Dispose(103-107)Task(27-72)Task(74-80)Task(82-88)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (csharp)
Refactors the data layer by specifying UUID types for IDs in entity configurations, ensuring data integrity and consistency. Improves test project discovery by sorting the results for consistent execution across environments. Enhances the robustness of database initialization in integration tests by adding exception handling. Rolls back transactions safely by checking for null before attempting to rollback. Removes docker layer caching to streamline the CI process.
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (11)
.github/workflows/workflow-ci.yml (1)
37-37: Ótima adição da ordenação para execução determinística.A ordenação dos projetos de teste garante execução consistente entre diferentes ambientes e execuções do CI. O padrão atualizado corretamente inclui os novos tipos de projetos de teste (ArchitectureTests, IntegrationTests, UnitTests).
Consideração opcional: Como os testes de integração agora utilizam Testcontainers (PostgreSQL), considere adicionar cache de imagens Docker para melhorar o desempenho do CI. Sem cache, o Testcontainers baixará as imagens em cada execução, adicionando ~30s-2min ao tempo de CI.
💡 Exemplo de implementação de cache para Testcontainers
Adicione este step antes do "Run Tests":
- name: Cache Docker Images uses: actions/cache@v4 with: path: /tmp/docker-images key: docker-${{ runner.os }}-postgres-15-alpine restore-keys: | docker-${{ runner.os }}-postgres- - name: Load Cached Docker Images run: | if [ -d "/tmp/docker-images" ]; then echo "🔄 Carregando imagens Docker do cache..." for img in /tmp/docker-images/*.tar; do [ -f "$img" ] && docker load -i "$img" done else echo "📦 Baixando imagens Docker necessárias..." docker pull postgres:15-alpine mkdir -p /tmp/docker-images docker save postgres:15-alpine -o /tmp/docker-images/postgres-15-alpine.tar fiNota: Ajuste a tag da imagem PostgreSQL (
postgres:15-alpine) para corresponder à versão utilizada nos seus testes de integração.InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/UserConfigTests.cs (1)
23-92: Adicionar verificação do índice único no Email.O teste cobre bem as principais configurações da entidade, mas não verifica o índice único definido na propriedade
UserConfig.cs:_ = builder.HasIndex(x => x.Email) .HasDatabaseName("idx_user_email") .IsUnique();Índices são importantes para integridade e performance do banco de dados. Considere adicionar a verificação:
🔎 Sugestão de código para verificar o índice
Adicione após a linha 71:
emailProperty.GetColumnName().ShouldBe("email"); (!emailProperty.IsNullable).ShouldBeTrue(); + +// Verifica índice único no Email +var emailIndex = entityType.GetIndexes() + .FirstOrDefault(i => i.Properties.Count == 1 && i.Properties[0].Name == nameof(User.Email)); +_ = emailIndex.ShouldNotBeNull(); +emailIndex.IsUnique.ShouldBeTrue(); +emailIndex.GetDatabaseName().ShouldBe("idx_user_email");Melhorias opcionais adicionais:
- As verificações de
MaxLength(255 caracteres para Name, Email e Password) eHasDefaultValue(0)para TelegramChatId não estão sendo testadas.- O estilo de asserção
(!property.IsNullable).ShouldBeTrue()poderia ser mais legível comoproperty.IsNullable.ShouldBeFalse().- O método tem mais de 70 linhas - considere dividir em testes menores para melhor isolamento e mensagens de falha mais claras (ex:
UserConfig_ShouldConfigureTableName,UserConfig_ShouldConfigurePrimaryKey, etc.).InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/JobScheduleConfigTests.cs (2)
13-21: Considere remover este teste redundante.O teste
JobScheduleConfig_ShouldConfigureEntityCorrectlyjá instancia a classeJobScheduleConfige valida sua funcionalidade completa. Este teste de instanciação simples não adiciona cobertura significativa e pode ser removido para simplificar a suite de testes.
35-35: Padrão de asserção incomum com operador de descarte.As linhas que usam
_ = variable.ShouldNotBeNull();empregam um padrão incomum. As asserções do Shouldly retornamvoid, portanto a atribuição ao descarte (_) é desnecessária. O padrão convencional seria simplesmentevariable.ShouldNotBeNull();.🔎 Sugestão para simplificar as asserções
// Assert var entityType = builder.Model.FindEntityType(typeof(JobSchedule)); -_ = entityType.ShouldNotBeNull(); +entityType.ShouldNotBeNull(); // Verifica tabela entityType.GetTableName().ShouldBe("job_schedule"); // Verifica chave primária var primaryKey = entityType.FindPrimaryKey(); -_ = primaryKey.ShouldNotBeNull(); +primaryKey.ShouldNotBeNull(); primaryKey.Properties.Count.ShouldBe(1); primaryKey.Properties[0].Name.ShouldBe(nameof(JobSchedule.Id)); // Verifica propriedade Id var idProperty = entityType.FindProperty(nameof(JobSchedule.Id)); -_ = idProperty.ShouldNotBeNull(); +idProperty.ShouldNotBeNull();Aplicar o mesmo padrão para as demais verificações de
ShouldNotBeNull().Also applies to: 42-42, 48-48, 56-56, 63-63, 69-69, 76-76
InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/InvoiceConfigTests.cs (1)
13-21: Considere se este teste agrega valor suficiente.Este teste verifica apenas que
InvoiceConfigpode ser instanciada sem lançar exceção. Como a classe não possui lógica de construtor, dependências ou inicialização estática, o teste oferece cobertura mínima. Se este padrão não for usado consistentemente em outros testes de configuração de entidade, considere removê-lo.InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/ScanEmailDefinitionConfigTests.cs (1)
40-84: Validações das propriedades estão funcionalmente corretas, mas podem ser mais abrangentes.As validações de chave primária, tipos de coluna, nomes de coluna e nullability estão corretas e alinhadas com
ScanEmailDefinitionConfig. No entanto, o teste poderia ser mais completo ao verificar também as restrições deMaxLength(255)configuradas para as propriedades de string (Beneficiary,Description,SenderEmailAddress,AttachmentFileName) e a conversãoHasConversion<int>()paraInvoiceType.🔎 Exemplo de como adicionar validação de MaxLength
// Verifica propriedade Beneficiary var beneficiaryProperty = entityType.FindProperty(nameof(ScanEmailDefinition.Beneficiary)); _ = beneficiaryProperty.ShouldNotBeNull(); beneficiaryProperty.GetColumnName().ShouldBe("beneficiary"); (!beneficiaryProperty.IsNullable).ShouldBeTrue(); +beneficiaryProperty.GetMaxLength().ShouldBe(255);InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/EmailAuthTokenConfigTests.cs (3)
14-21: Considere remover este teste de baixo valor.O teste
EmailAuthTokenConfig_ShouldNotThrowErrorWhenInstantiatedapenas verifica que o construtor não lança exceção, o que é trivial para uma classe de configuração simples. Este tipo de teste não agrega valor significativo à suite de testes.
61-83: Considere adicionar verificações para constraints de MaxLength.O teste valida nomes de colunas, tipos e nullability, mas não verifica as constraints de
MaxLengthdefinidas na configuração (AccessToken: 512, RefreshToken: 512, NonceValue: 64, TokenProvider: 25). Adicionar essas verificações tornaria o teste mais completo e detectaria mudanças inadvertidas nesses limites.🔎 Exemplo de verificação de MaxLength
// Verifica propriedade AccessToken var accessTokenProperty = entityType.FindProperty(nameof(EmailAuthToken.AccessToken)); _ = accessTokenProperty.ShouldNotBeNull(); accessTokenProperty.GetColumnName().ShouldBe("access_token"); +accessTokenProperty.GetMaxLength().ShouldBe(512); (!accessTokenProperty.IsNullable).ShouldBeTrue(); // Verifica propriedade RefreshToken var refreshTokenProperty = entityType.FindProperty(nameof(EmailAuthToken.RefreshToken)); _ = refreshTokenProperty.ShouldNotBeNull(); refreshTokenProperty.GetColumnName().ShouldBe("refresh_token"); +refreshTokenProperty.GetMaxLength().ShouldBe(512); (!refreshTokenProperty.IsNullable).ShouldBeTrue(); // Verifica propriedade NonceValue var nonceValueProperty = entityType.FindProperty(nameof(EmailAuthToken.NonceValue)); _ = nonceValueProperty.ShouldNotBeNull(); nonceValueProperty.GetColumnName().ShouldBe("nonce_value"); +nonceValueProperty.GetMaxLength().ShouldBe(64); (!nonceValueProperty.IsNullable).ShouldBeTrue(); // Verifica propriedade TokenProvider var tokenProviderProperty = entityType.FindProperty(nameof(EmailAuthToken.TokenProvider)); _ = tokenProviderProperty.ShouldNotBeNull(); tokenProviderProperty.GetColumnName().ShouldBe("token_provider"); +tokenProviderProperty.GetMaxLength().ShouldBe(25); (!tokenProviderProperty.IsNullable).ShouldBeTrue();
51-103: Simplifique as verificações de nullability para melhor legibilidade.O padrão
(!property.IsNullable).ShouldBeTrue()usado nas linhas 51, 59, 65, 71, 77, 83, 89, 96 e 103 pode ser simplificado paraproperty.IsNullable.ShouldBeFalse(), o que torna a intenção mais clara e direta.🔎 Exemplo de simplificação
-(!idProperty.IsNullable).ShouldBeTrue(); +idProperty.IsNullable.ShouldBeFalse();Aplique o mesmo padrão para todas as outras verificações de nullability no teste.
InvoiceReminder.IntegrationTests/Data/Repository/UnitOfWorkIntegrationTests.cs (1)
45-53:UserFakerduplicado - considere reutilizarTestData.UserFaker().Este arquivo define seu próprio
UserFakerque é praticamente idêntico aoTestData.UserFaker()(exceto pelos camposCreatedAt/UpdatedAtausentes em ambos). Para manter consistência e evitar duplicação, considere reutilizar o helper centralizado.🔎 Refatoração sugerida
+using InvoiceReminder.IntegrationTests.Data.Utils; ... - private static Faker<User> UserFaker() - { - return new Faker<User>() - .RuleFor(u => u.Id, _ => Guid.NewGuid()) - .RuleFor(u => u.TelegramChatId, f => f.Random.Long(100000000, long.MaxValue)) - .RuleFor(u => u.Name, f => f.Person.FullName) - .RuleFor(u => u.Email, f => f.Internet.Email()) - .RuleFor(u => u.Password, f => f.Internet.Password(length: 16, memorable: false)); - } + // Use TestData.UserFaker() insteadE nas chamadas:
- var user = UserFaker().Generate(); + var user = TestData.UserFaker().Generate();InvoiceReminder.IntegrationTests/Data/Repository/BaseRepositoryIntegrationTests.cs (1)
23-43: Considere adicionar isolamento de dados entre testes.Os testes atualmente persistem dados no banco PostgreSQL sem limpeza entre execuções. Isso pode causar testes instáveis, especialmente em testes como
GetAll_Should_Return_All_Entities(linha 254) que usaShouldBeGreaterThanOrEqualTo(3)ao invés de verificar uma contagem exata.Considere implementar um dos seguintes padrões:
- Usar transações que são revertidas após cada teste
- Limpar dados específicos no TestCleanup
- Usar banco de dados isolado por teste (se viável com Testcontainers)
💡 Exemplo de padrão com transação
private CoreDbContext _dbContext; private BaseRepository<CoreDbContext, User> _userRepository; private BaseRepository<CoreDbContext, Invoice> _invoiceRepository; private UnitOfWork _unitOfWork; +private IDbContextTransaction _transaction; [TestInitialize] public void TestInitialize() { var options = new DbContextOptionsBuilder<CoreDbContext>() .UseNpgsql(DatabaseFixture.ConnectionString) .Options; _dbContext = new CoreDbContext(options); + _transaction = _dbContext.Database.BeginTransaction(); _userRepository = new BaseRepository<CoreDbContext, User>(_dbContext); _invoiceRepository = new BaseRepository<CoreDbContext, Invoice>(_dbContext); _unitOfWork = new UnitOfWork(_dbContext, Substitute.For<ILogger<UnitOfWork>>()); } [TestCleanup] public void TestCleanup() { + _transaction?.Rollback(); + _transaction?.Dispose(); _unitOfWork?.Dispose(); _userRepository?.Dispose(); _invoiceRepository?.Dispose(); _dbContext?.Dispose(); }
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (22)
.github/workflows/workflow-ci.ymlInvoiceReminder.Data/Migrations/20250930210104_Initial_Create.csInvoiceReminder.Data/Persistence/EntitiesConfig/JobScheduleConfig.csInvoiceReminder.Data/Persistence/EntitiesConfig/ScanEmailDefinitionConfig.csInvoiceReminder.Data/Repository/UnitOfWork.csInvoiceReminder.IntegrationTests/Data/ContainerSetup/DatabaseFixture.csInvoiceReminder.IntegrationTests/Data/Repository/BaseRepositoryIntegrationTests.csInvoiceReminder.IntegrationTests/Data/Repository/EmailAuthTokenRepositoryIntegrationTests.csInvoiceReminder.IntegrationTests/Data/Repository/InvoiceRepositoryIntegrationTests.csInvoiceReminder.IntegrationTests/Data/Repository/JobScheduleRepositoryIntegrationTests.csInvoiceReminder.IntegrationTests/Data/Repository/ScanEmailDefinitionRepositoryIntegrationTests.csInvoiceReminder.IntegrationTests/Data/Repository/UnitOfWorkIntegrationTests.csInvoiceReminder.IntegrationTests/Data/Repository/UserRepositoryIntegrationTests.csInvoiceReminder.IntegrationTests/Data/Utils/TestData.csInvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/EmailAuthTokenConfigTests.csInvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/InvoiceConfigTests.csInvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/JobScheduleConfigTests.csInvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/ScanEmailDefinitionConfigTests.csInvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/UserConfigTests.csInvoiceReminder.UnitTests.Infrastructure/InvoiceReminder.UnitTests.Infrastructure.csprojInvoiceReminder.UnitTests.JobScheduler/HostedService/QuartzHostedServiceTests.csInvoiceReminder.UnitTests.JobScheduler/JobSettings/CronJobTests.cs
🚧 Files skipped from review as they are similar to previous changes (4)
- InvoiceReminder.UnitTests.JobScheduler/HostedService/QuartzHostedServiceTests.cs
- InvoiceReminder.IntegrationTests/Data/ContainerSetup/DatabaseFixture.cs
- InvoiceReminder.IntegrationTests/Data/Repository/UserRepositoryIntegrationTests.cs
- InvoiceReminder.Data/Persistence/EntitiesConfig/ScanEmailDefinitionConfig.cs
🧰 Additional context used
🧬 Code graph analysis (12)
InvoiceReminder.UnitTests.JobScheduler/JobSettings/CronJobTests.cs (2)
InvoiceReminder.JobScheduler.UnitTests/JobSettings/CronJobTests.cs (3)
CronJobTests(11-111)Execute_ShouldCreateScopeResolveServiceAndSendMessage(44-65)CronJobTests(23-42)InvoiceReminder.JobScheduler.UnitTests/HostedService/QuartzHostedServiceTests.cs (1)
QuartzHostedServiceTests(11-263)
InvoiceReminder.IntegrationTests/Data/Utils/TestData.cs (3)
InvoiceReminder.Domain/Entities/EmailAuthToken.cs (1)
EmailAuthToken(3-12)InvoiceReminder.Domain/Entities/JobSchedule.cs (1)
JobSchedule(3-7)InvoiceReminder.Domain/Entities/ScanEmailDefinition.cs (1)
ScanEmailDefinition(5-13)
InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/EmailAuthTokenConfigTests.cs (2)
InvoiceReminder.Data/Persistence/EntitiesConfig/EmailAuthTokenConfig.cs (1)
EmailAuthTokenConfig(10-64)InvoiceReminder.Domain/Entities/EmailAuthToken.cs (1)
EmailAuthToken(3-12)
InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/InvoiceConfigTests.cs (1)
InvoiceReminder.Data/Persistence/EntitiesConfig/InvoiceConfig.cs (2)
InvoiceConfig(10-62)Configure(12-61)
InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/UserConfigTests.cs (1)
InvoiceReminder.Data/Persistence/EntitiesConfig/UserConfig.cs (2)
UserConfig(10-59)Configure(12-58)
InvoiceReminder.Data/Repository/UnitOfWork.cs (1)
InvoiceReminder.Data/Repository/BaseRepository.cs (2)
Dispose(79-87)Dispose(89-93)
InvoiceReminder.IntegrationTests/Data/Repository/ScanEmailDefinitionRepositoryIntegrationTests.cs (5)
InvoiceReminder.IntegrationTests/Data/ContainerSetup/DatabaseFixture.cs (2)
Task(44-51)Task(53-62)InvoiceReminder.IntegrationTests/Data/Repository/EmailAuthTokenRepositoryIntegrationTests.cs (2)
Task(260-271)Task(273-283)InvoiceReminder.Data/Repository/UnitOfWork.cs (8)
UnitOfWork(12-113)UnitOfWork(20-25)UnitOfWork(109-112)Dispose(90-101)Dispose(103-107)Task(27-72)Task(74-80)Task(82-88)InvoiceReminder.Domain/Entities/ScanEmailDefinition.cs (1)
ScanEmailDefinition(5-13)InvoiceReminder.IntegrationTests/Data/Utils/TestData.cs (1)
TestData(7-84)
InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/ScanEmailDefinitionConfigTests.cs (2)
InvoiceReminder.Data/Persistence/EntitiesConfig/ScanEmailDefinitionConfig.cs (2)
ScanEmailDefinitionConfig(10-64)Configure(12-63)InvoiceReminder.Domain/Entities/ScanEmailDefinition.cs (1)
ScanEmailDefinition(5-13)
InvoiceReminder.IntegrationTests/Data/Repository/EmailAuthTokenRepositoryIntegrationTests.cs (3)
InvoiceReminder.Data/Repository/UnitOfWork.cs (8)
UnitOfWork(12-113)UnitOfWork(20-25)UnitOfWork(109-112)Dispose(90-101)Dispose(103-107)Task(27-72)Task(74-80)Task(82-88)InvoiceReminder.Domain/Entities/EmailAuthToken.cs (1)
EmailAuthToken(3-12)InvoiceReminder.IntegrationTests/Data/Utils/TestData.cs (1)
TestData(7-84)
InvoiceReminder.IntegrationTests/Data/Repository/InvoiceRepositoryIntegrationTests.cs (1)
InvoiceReminder.IntegrationTests/Data/ContainerSetup/DatabaseFixture.cs (3)
TestClass(8-63)Task(44-51)Task(53-62)
InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/JobScheduleConfigTests.cs (2)
InvoiceReminder.Data/Persistence/EntitiesConfig/JobScheduleConfig.cs (2)
JobScheduleConfig(10-44)Configure(12-43)InvoiceReminder.Domain/Entities/JobSchedule.cs (1)
JobSchedule(3-7)
InvoiceReminder.IntegrationTests/Data/Repository/JobScheduleRepositoryIntegrationTests.cs (3)
InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/JobScheduleConfigTests.cs (1)
TestClass(10-81)InvoiceReminder.Domain/Entities/JobSchedule.cs (1)
JobSchedule(3-7)InvoiceReminder.IntegrationTests/Data/Utils/TestData.cs (1)
TestData(7-84)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (csharp)
🔇 Additional comments (37)
InvoiceReminder.UnitTests.Infrastructure/InvoiceReminder.UnitTests.Infrastructure.csproj (2)
15-23: Boa prática: remoção de dependências do EF Core dos testes unitários.A remoção das referências aos pacotes do Entity Framework Core (Microsoft.EntityFrameworkCore, Microsoft.EntityFrameworkCore.Relational, Microsoft.EntityFrameworkCore.Sqlite) dos testes unitários está alinhada com as melhores práticas. Testes unitários devem usar mocks (NSubstitute está presente) para interações com banco de dados, enquanto os testes de integração com Testcontainers devem estar em projetos separados.
Verifique se todos os testes unitários compilam corretamente sem essas dependências diretas.
12-12: Refatoração validada - estrutura consistente.A referência ao projeto
InvoiceReminder.UnitTests.SUT.Assetsestá correta e o projeto existe com a estrutura esperada. A remoção das dependências do Entity Framework Core é uma boa prática para testes unitários, mantendo o foco em testes isolados com mocks via NSubstitute. As dependências estão adequadas para o escopo de testes unitários.InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/UserConfigTests.cs (1)
13-21: Teste de instanciação está correto.O teste verifica que a classe
UserConfigpode ser instanciada sem lançar exceções. Embora seja um teste básico (já que não há lógica no construtor), ele pode ser útil para detectar problemas futuros caso alguém adicione lógica ao construtor.InvoiceReminder.Data/Persistence/EntitiesConfig/JobScheduleConfig.cs (3)
24-27: Consistência: Tipagem UUID aplicada à chave estrangeira.A adição de
HasColumnType("uuid")para a propriedadeUserIdmantém consistência com a tipagem explícita aplicada à propriedadeId. Isso garante que a chave estrangeira tenha o mesmo tipo de coluna que a chave primária referenciada, melhorando a integridade referencial.
18-22: Tipagem explícita UUID para PostgreSQL está implementada de forma consistente.A adição de
HasColumnType("uuid")para a propriedadeIdmelhora a consistência entre o tipo C#Guide o tipo de coluna PostgreSQL. Esta mudança está implementada de forma sistemática em todas as configurações de entidades (Invoice, ScanEmailDefinition, User, EmailAuthToken e JobSchedule), e as migrações do EF Core foram adequadamente atualizadas no Designer e ModelSnapshot.
6-6: O nome do assembly de testes atualizado está correto e consistente.A alteração do atributo
InternalsVisibleToparaInvoiceReminder.UnitTests.Infrastructureestá validada. O projeto de testes foi encontrado no repositório com a estrutura esperada, e a configuração é consistente em todos os arquivos de entidade do Data Layer (JobScheduleConfig.cs, InvoiceConfig.cs, UserConfig.cs, ScanEmailDefinitionConfig.cs e EmailAuthTokenConfig.cs). Nenhuma referência ao nome antigo permanece no codebase.InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/InvoiceConfigTests.cs (3)
1-8: LGTM! Imports e namespace estão corretos.Os imports são apropriados para testar configurações de entidades do EF Core, e o namespace segue a nova estrutura de organização dos testes.
10-11: LGTM! Declaração da classe de teste está correta.A classe segue as convenções do MSTest e o modificador
sealedé apropriado para classes de teste.
23-107: Excelente! Teste de configuração abrangente e bem estruturado.Este teste valida de forma completa a configuração da entidade Invoice:
- Verifica corretamente o nome da tabela, chave primária e todas as propriedades
- Confirma mapeamentos de colunas, tipos, nulabilidade e restrições
- Inclui propriedades herdadas (CreatedAt, UpdatedAt)
- Uso correto de
ConventionSetvazio para teste isolado da configuraçãoA cobertura está alinhada com toda a configuração definida em
InvoiceConfig.cs.InvoiceReminder.UnitTests.JobScheduler/JobSettings/CronJobTests.cs (2)
9-9: Alteração de namespace aprovada.A reorganização do namespace de
InvoiceReminder.JobScheduler.UnitTests.JobSettingsparaInvoiceReminder.UnitTests.JobScheduler.JobSettingsestá alinhada com os objetivos do PR de melhorar a clareza e manutenibilidade dos projetos de teste.
62-68: Simplificação das asserções de log aprovada.A refatoração para usar
Arg.Any<>()torna as asserções mais concisas e focadas no que realmente importa (verificar que o log foi chamado comLogLevel.Information). O uso denullpara o parâmetro de exceção é apropriado para este cenário de sucesso.InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/ScanEmailDefinitionConfigTests.cs (6)
1-8: Importações e namespace apropriados.As importações incluem todas as dependências necessárias para testar configurações de entidades EF Core usando
ModelBuildereConventionSet. O uso do Shouldly para asserções está alinhado com o padrão do projeto.
10-12: Declaração da classe de teste está correta.O uso de
sealedé uma boa prática para classes de teste que não precisam de herança. A convenção de nomenclatura está consistente com o padrão do projeto.
13-21: Teste de instanciação é adequado.Este teste de fumaça básico garante que a classe de configuração pode ser instanciada sem erros, o que é uma verificação válida para classes de configuração EF Core.
23-38: Configuração do teste e validação da tabela estão corretas.O uso de
ConventionSetvazia para testes isolados é apropriado. A validação do nome da tabela está alinhada com a configuração emScanEmailDefinitionConfig.
91-103: Validações das propriedades de auditoria estão corretas.As verificações de
CreatedAteUpdatedAtestão apropriadas, incluindo mapeamento de colunas, tipos e nullability. A validação de propriedades herdadas deEntityDefaultsdemonstra uma cobertura de teste completa.
1-104: Nenhum erro de sintaxe encontrado na entidade de domínio.A propriedade
SenderEmailAddressemInvoiceReminder.Domain/Entities/ScanEmailDefinition.cs(linha 11) está sintaticamente correta:public string SenderEmailAddress { get; set; }. Não há duplo ponto-e-vírgula ou qualquer outro erro de sintaxe que impeça a compilação.Likely an incorrect or invalid review comment.
InvoiceReminder.Data/Repository/UnitOfWork.cs (1)
27-71: Implementação robusta de transações com tratamento adequado de nulos.A lógica de
SaveChangesAsyncestá bem estruturada com tratamento de cancelamento e rollback. O uso do operador?.na linha 63 (await transaction?.RollbackAsync(...)) garante que o rollback só será executado se a transação tiver sido iniciada com sucesso, evitandoNullReferenceException.O padrão de abrir conexão → iniciar transação → salvar → commit está correto, e o bloco
finallygarante a liberação dos recursos.InvoiceReminder.IntegrationTests/Data/Repository/ScanEmailDefinitionRepositoryIntegrationTests.cs (2)
1-46: Estrutura de testes de integração bem organizada.A configuração do teste está adequada: cria um contexto real conectado ao PostgreSQL via Testcontainers, utiliza mocks para loggers, e o
TestCleanupgarante a liberação dos recursos. A inicialização de camposreadonlyno construtor é uma boa prática.
586-609: Métodos auxiliares bem estruturados para criação de dados de teste.Os helpers
CreateAndSaveUserAsynceCreateAndSaveScanEmailDefinitionAsyncencapsulam corretamente a criação e persistência de entidades, respeitando as relações de chave estrangeira (oScanEmailDefinitionprecisa de umUserexistente).InvoiceReminder.IntegrationTests/Data/Repository/EmailAuthTokenRepositoryIntegrationTests.cs (1)
1-46: Testes de integração consistentes com o padrão do projeto.A estrutura segue o mesmo padrão dos outros testes de repositório: inicialização via construtor, cleanup via
TestCleanup, e uso doDatabaseFixturepara conexão com PostgreSQL. Cobertura adequada para os métodos do repositório.InvoiceReminder.IntegrationTests/Data/Utils/TestData.cs (1)
33-53: Boa utilização de dados de domínio realistas.O
InvoiceFakerutiliza nomes de bancos brasileiros reais e valores monetários apropriados, tornando os dados de teste mais representativos do cenário real de uso.InvoiceReminder.Data/Migrations/20250930210104_Initial_Create.cs (2)
33-57: Dados de seed com senhas hardcoded - aceitável para desenvolvimento.Os dados de seed inserem usuários de teste com senhas fixas (hash SHA-256 de "123456"). Isso é adequado para ambiente de desenvolvimento/testes, mas garanta que esses dados não sejam utilizados em produção e que a documentação indique que estas são credenciais de teste.
Verifique se há documentação indicando que os usuários seed são apenas para desenvolvimento/testes.
163-192: Índices bem definidos para otimização de consultas.Os índices nas colunas de chave estrangeira (
user_id) e o índice único no email do usuário (idx_user_email) estão corretamente configurados, garantindo performance nas consultas e integridade dos dados.InvoiceReminder.IntegrationTests/Data/Repository/JobScheduleRepositoryIntegrationTests.cs (1)
1-46: Testes de integração consistentes com o padrão estabelecido.A estrutura segue fielmente o padrão dos outros testes de repositório no projeto. O uso de
BulkInsertAsyncno teste de múltiplos registros (linha 174) demonstra cobertura de diferentes métodos de inserção.InvoiceReminder.IntegrationTests/Data/Repository/UnitOfWorkIntegrationTests.cs (1)
186-248: Excelente cobertura de testes para cenários de rollback.Os testes
SaveChangesAsync_Should_Rollback_On_Invalid_DataeSaveChangesAsync_Should_Rollback_Transaction_On_Constraint_Violationverificam corretamente o comportamento de rollback em caso de falha, incluindo a verificação de logging de erro. A estratégia de criar um novo contexto após a falha para o teste de constraint violation (linhas 228-232) é apropriada.InvoiceReminder.IntegrationTests/Data/Repository/InvoiceRepositoryIntegrationTests.cs (2)
1-46: Testes de integração bem estruturados paraInvoiceRepository.A implementação segue o padrão consistente dos outros testes de repositório. O teste de whitespace no barcode (linha 156-172) é importante para garantir que a busca funciona mesmo com espaços extras na entrada.
263-288: Métodos auxiliares seguem o padrão estabelecido.Os helpers
CreateAndSaveUserAsynceCreateAndSaveInvoiceAsyncestão consistentes com os de outras classes de teste, garantindo a criação correta de entidades respeitando as dependências de chave estrangeira.InvoiceReminder.IntegrationTests/Data/Repository/BaseRepositoryIntegrationTests.cs (9)
47-97: Ótima cobertura de testes para AddAsync.Os testes cobrem adequadamente os cenários de adição de entidade, verificando o estado da entidade, a persistência após SaveChanges, e o retorno correto. O uso de DbContext separado para verificação de persistência é uma boa prática.
103-175: Excelente cobertura de cenários de BulkInsertAsync.Os testes cobrem casos importantes incluindo inserção múltipla, validação de timestamps automáticos, persistência, coleção vazia e tratamento de cancelamento. A validação de timestamps (linha 126) garante que o comportamento de auditoria funciona corretamente.
181-226: Testes de GetByIdAsync bem estruturados.Os testes cobrem os cenários principais: recuperação por ID existente, retorno nulo para ID inexistente, e tratamento de cancelamento. As validações com ShouldSatisfyAllConditions garantem verificações completas.
232-283: Ótimos testes para GetAll e comportamento NoTracking.Os testes verificam corretamente a recuperação de todas as entidades e o comportamento AsNoTracking (confirmando EntityState.Detached na linha 282). O padrão de criar um repositório novo para garantir leitura fresca do banco é apropriado.
302-357: Testes de Remove cobrem cenários importantes.Os testes verificam adequadamente a marcação como deletado, a remoção efetiva do banco após SaveChanges, e o tratamento correto de entidades desanexadas (linha 349). O teste de desanexamento é particularmente importante para cenários de APIs desconectadas.
363-442: Cobertura completa para operação Update.Os testes cobrem todos os aspectos importantes: marcação como modificado, persistência de mudanças, tratamento de entidades desanexadas, e verificação do retorno. O cenário de desanexamento (linha 416) é essencial para APIs que trabalham com DTOs.
448-540: Excelente cobertura de consultas com Where.Os testes cobrem bem diferentes cenários de filtragem: único resultado, múltiplos resultados, nenhum resultado, e predicados complexos. O uso de
RuleForpara definir valores específicos nos testes garante resultados determinísticos.
546-585: Testes de Dispose garantem gerenciamento correto de recursos.Os testes verificam que o DbContext é propriamente liberado (linha 563) e que múltiplas chamadas a Dispose são seguras (linhas 579-584). Isso garante que o repositório segue o padrão IDisposable corretamente.
591-600: Helper method útil para criar repositórios isolados.O método
CreateFreshRepository<T>fornece uma maneira limpa de criar instâncias de repositório com contexto novo, útil para testes que precisam verificar persistência com contexto separado.
Implements bulk remove and update functionalities in the base repository for improved data manipulation efficiency. Also adds timestamping of updated entities during bulk updates to maintain audit trails. Removes redundant tests and adds data seeding to integration tests for better test coverage.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (5)
InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/InvoiceConfigTests.cs (1)
41-41: Considere simplificar as asserções de nulabilidade.O padrão
(!property.IsNullable).ShouldBeTrue()funciona corretamente, mas a leitura seria mais direta usandoproperty.IsNullable.ShouldBeFalse().🔎 Sugestão de refatoração para melhor legibilidade
- (!idProperty.IsNullable).ShouldBeTrue(); + idProperty.IsNullable.ShouldBeFalse(); - (!userIdProperty.IsNullable).ShouldBeTrue(); + userIdProperty.IsNullable.ShouldBeFalse(); - (!bankProperty.IsNullable).ShouldBeTrue(); + bankProperty.IsNullable.ShouldBeFalse(); - (!beneficiaryProperty.IsNullable).ShouldBeTrue(); + beneficiaryProperty.IsNullable.ShouldBeFalse(); - (!barcodeProperty.IsNullable).ShouldBeTrue(); + barcodeProperty.IsNullable.ShouldBeFalse(); - (!amountProperty.IsNullable).ShouldBeTrue(); + amountProperty.IsNullable.ShouldBeFalse(); - (!dueDateProperty.IsNullable).ShouldBeTrue(); + dueDateProperty.IsNullable.ShouldBeFalse(); - (!createdAtProperty.IsNullable).ShouldBeTrue(); + createdAtProperty.IsNullable.ShouldBeFalse(); - (!updatedAtProperty.IsNullable).ShouldBeTrue(); + updatedAtProperty.IsNullable.ShouldBeFalse();Also applies to: 49-49, 55-55, 62-62, 69-69, 75-75, 82-82, 89-89, 96-96
InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/JobScheduleConfigTests.cs (1)
17-17: Considere usar o ConventionSet padrão do EF Core.A criação de um
ConventionSetvazio pode não aplicar as convenções padrão do EF Core (como descoberta de chaves, nomenclatura, etc.). Embora o teste funcione porqueJobScheduleConfigconfigura explicitamente todas as propriedades, usar as convenções padrão tornaria o teste mais representativo do comportamento real do EF Core.🔎 Refatoração sugerida
// Arrange -var builder = new ModelBuilder(new ConventionSet()); +var builder = new ModelBuilder(ConventionSet.CreateConventionSet(new DbContext(new DbContextOptions<DbContext>()))); var config = new JobScheduleConfig();Ou, alternativamente, use um
DbContextOptionsBuilderreal:// Arrange +var options = new DbContextOptionsBuilder<DbContext>() + .UseInMemoryDatabase("test") + .Options; +var builder = new ModelBuilder(options.GetExtension<CoreOptionsExtension>().Model.ConventionSet); -var builder = new ModelBuilder(new ConventionSet()); var config = new JobScheduleConfig();InvoiceReminder.Data/Repository/BaseRepository.cs (1)
47-55: BulkUpdateAsync implementado corretamente com atualização de timestamp.A implementação atualiza adequadamente
UpdatedAtantes da operação bulk, garantindo auditoria consistente. O padrão de reflexão usado é consistente comBulkInsertAsync.No entanto, considere que a abordagem baseada em reflexão falha silenciosamente se a propriedade não existir. Para maior robustez, você pode considerar usar uma interface ou classe base que garanta a presença dessas propriedades.
💡 Refatoração opcional para maior segurança de tipos
Considere criar uma interface ou constraint genérico para entidades com timestamps:
public interface ITimestampedEntity { DateTime CreatedAt { get; set; } DateTime UpdatedAt { get; set; } } // Então no método: public virtual async Task BulkUpdateAsync(ICollection<TEntity> entities, CancellationToken cancellationToken = default) where TEntity : ITimestampedEntity { foreach (var entity in entities) { entity.UpdatedAt = DateTime.UtcNow; } await _dbContext.BulkUpdateAsync(entities, cancellationToken: cancellationToken); }Isso eliminaria a necessidade de reflexão e forneceria verificação em tempo de compilação.
InvoiceReminder.IntegrationTests/Data/Utils/TestData.cs (2)
17-18: Timestamps do UserFaker agora definidos corretamente!Ótimo trabalho ao adicionar
CreatedAteUpdatedAtaoUserFaker, resolvendo o problema apontado na revisão anterior.No entanto, há uma inconsistência lógica:
Date.Past()pode retornar datas muito antigas (até 1 ano atrás por padrão), enquantoDate.Recent()retorna datas dos últimos dias. Isso pode resultar emUpdatedAtanterior aCreatedAt, violando a lógica temporal de entidades.🔎 Correção sugerida para garantir UpdatedAt >= CreatedAt
public static Faker<User> UserFaker() { return new Faker<User>() .RuleFor(u => u.Id, _ => Guid.NewGuid()) .RuleFor(u => u.TelegramChatId, f => f.Random.Long(100000000, long.MaxValue)) .RuleFor(u => u.Name, f => f.Person.FullName) .RuleFor(u => u.Email, f => f.Internet.Email()) .RuleFor(u => u.Password, f => f.Internet.Password(length: 16, memorable: false)) - .RuleFor(u => u.CreatedAt, f => f.Date.Past().ToUniversalTime()) - .RuleFor(u => u.UpdatedAt, f => f.Date.Recent().ToUniversalTime()); + .RuleFor(u => u.CreatedAt, f => f.Date.Past().ToUniversalTime()) + .RuleFor(u => u.UpdatedAt, (f, u) => f.Date.Between(u.CreatedAt, DateTime.UtcNow).ToUniversalTime()); }Isso garante que
UpdatedAtsempre será maior ou igual aCreatedAt.
21-33: Inconsistência de timestamps em todos os Fakers.Todos os fakers (
EmailAuthTokenFaker,InvoiceFaker,JobScheduleFaker,ScanEmailDefinitionFaker) têm a mesma inconsistência lógica observada noUserFaker: usarDate.Past()paraCreatedAteDate.Recent()paraUpdatedAtpode resultar emUpdatedAtanterior aCreatedAt.🔎 Correção sugerida para todos os Fakers
Aplique o mesmo padrão de correção a todos os fakers, garantindo que
UpdatedAtesteja sempre entreCreatedAteDateTime.UtcNow:// Para EmailAuthTokenFaker (linhas 31-32) -.RuleFor(e => e.CreatedAt, faker => faker.Date.Past().ToUniversalTime()) -.RuleFor(e => e.UpdatedAt, faker => faker.Date.Recent().ToUniversalTime()); +.RuleFor(e => e.CreatedAt, faker => faker.Date.Past().ToUniversalTime()) +.RuleFor(e => e.UpdatedAt, (faker, e) => faker.Date.Between(e.CreatedAt, DateTime.UtcNow).ToUniversalTime()); // Para InvoiceFaker (linhas 53-54) -.RuleFor(i => i.CreatedAt, faker => faker.Date.Past().ToUniversalTime()) -.RuleFor(i => i.UpdatedAt, faker => faker.Date.Recent().ToUniversalTime()); +.RuleFor(i => i.CreatedAt, faker => faker.Date.Past().ToUniversalTime()) +.RuleFor(i => i.UpdatedAt, (faker, i) => faker.Date.Between(i.CreatedAt, DateTime.UtcNow).ToUniversalTime()); // Para JobScheduleFaker (linhas 69-70) -.RuleFor(j => j.CreatedAt, faker => faker.Date.Past().ToUniversalTime()) -.RuleFor(j => j.UpdatedAt, faker => faker.Date.Recent().ToUniversalTime()); +.RuleFor(j => j.CreatedAt, faker => faker.Date.Past().ToUniversalTime()) +.RuleFor(j => j.UpdatedAt, (faker, j) => faker.Date.Between(j.CreatedAt, DateTime.UtcNow).ToUniversalTime()); // Para ScanEmailDefinitionFaker (linhas 83-84) -.RuleFor(s => s.CreatedAt, faker => faker.Date.Past().ToUniversalTime()) -.RuleFor(s => s.UpdatedAt, faker => faker.Date.Recent().ToUniversalTime()); +.RuleFor(s => s.CreatedAt, faker => faker.Date.Past().ToUniversalTime()) +.RuleFor(s => s.UpdatedAt, (faker, s) => faker.Date.Between(s.CreatedAt, DateTime.UtcNow).ToUniversalTime());Also applies to: 35-55, 57-71, 73-85
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
InvoiceReminder.Data/Interfaces/IBaseRepository.csInvoiceReminder.Data/Repository/BaseRepository.csInvoiceReminder.IntegrationTests/Data/Repository/BaseRepositoryIntegrationTests.csInvoiceReminder.IntegrationTests/Data/Utils/TestData.csInvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/EmailAuthTokenConfigTests.csInvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/InvoiceConfigTests.csInvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/JobScheduleConfigTests.csInvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/ScanEmailDefinitionConfigTests.csInvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/UserConfigTests.csInvoiceReminder.UnitTests.JobScheduler/JobSettings/CronJobTests.cs
🚧 Files skipped from review as they are similar to previous changes (3)
- InvoiceReminder.UnitTests.JobScheduler/JobSettings/CronJobTests.cs
- InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/ScanEmailDefinitionConfigTests.cs
- InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/UserConfigTests.cs
🧰 Additional context used
🧬 Code graph analysis (6)
InvoiceReminder.Data/Interfaces/IBaseRepository.cs (3)
InvoiceReminder.Data/Repository/BaseRepository.cs (1)
TEntity(77-87)InvoiceReminder.Data/Interfaces/IUnitOfWork.cs (2)
SaveChangesAsync(5-5)IUnitOfWork(3-6)InvoiceReminder.Application/AppServices/BaseAppService.cs (2)
BaseAppService(8-90)BulkInsertAsync(35-45)
InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/EmailAuthTokenConfigTests.cs (2)
InvoiceReminder.Data/Persistence/EntitiesConfig/EmailAuthTokenConfig.cs (1)
EmailAuthTokenConfig(10-64)InvoiceReminder.Domain/Entities/EmailAuthToken.cs (1)
EmailAuthToken(3-12)
InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/JobScheduleConfigTests.cs (1)
InvoiceReminder.Domain/Entities/JobSchedule.cs (1)
JobSchedule(3-7)
InvoiceReminder.Data/Repository/BaseRepository.cs (1)
InvoiceReminder.Data/Interfaces/IBaseRepository.cs (6)
Task(7-7)Task(8-8)Task(9-9)Task(10-10)Task(12-12)TEntity(14-14)
InvoiceReminder.IntegrationTests/Data/Utils/TestData.cs (4)
InvoiceReminder.Domain/Extensions/EntityExtensions.cs (1)
Guid(41-52)InvoiceReminder.Domain/Entities/EmailAuthToken.cs (1)
EmailAuthToken(3-12)InvoiceReminder.Domain/Entities/JobSchedule.cs (1)
JobSchedule(3-7)InvoiceReminder.Domain/Entities/ScanEmailDefinition.cs (1)
ScanEmailDefinition(5-13)
InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/InvoiceConfigTests.cs (1)
InvoiceReminder.Data/Persistence/EntitiesConfig/InvoiceConfig.cs (2)
InvoiceConfig(10-62)Configure(12-61)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (csharp)
🔇 Additional comments (10)
InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/EmailAuthTokenConfigTests.cs (1)
78-83: Problema anterior resolvido com sucesso!A verificação do tipo de coluna para
AccessTokenExpiryfoi adicionada corretamente na linha 82. Isso resolve a inconsistência apontada no comentário anterior e garante que a configuração de "timestamp with time zone" seja validada pelo teste.InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/InvoiceConfigTests.cs (2)
13-97: Excelente cobertura de testes!O teste valida de forma abrangente todos os aspectos da configuração do EF Core para a entidade
Invoice:
- Nome da tabela
- Chave primária
- Todas as propriedades (incluindo as herdadas de
EntityDefaults)- Nomes de colunas, tipos, nulabilidade, comprimentos máximos e geração de valores
A estrutura está clara e consistente com os outros testes de configuração do projeto.
16-21: A configuração deInternalsVisibleTojá está corretamente implementada. O arquivoInvoiceConfig.csna linha 6 contém o atributo[assembly: InternalsVisibleTo("InvoiceReminder.UnitTests.Infrastructure")], permitindo o acesso à classeinternala partir do projeto de testes. Nenhuma ação é necessária.InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/JobScheduleConfigTests.cs (1)
51-56: Validação de MaxLength corretamente implementada!Ótimo trabalho ao adicionar a validação de
MaxLengthna linha 55. Isso garante cobertura completa da configuração deCronExpression.InvoiceReminder.Data/Interfaces/IBaseRepository.cs (1)
9-10: Adição de métodos bulk está correta.As novas assinaturas
BulkRemoveAsynceBulkUpdateAsyncseguem o padrão existente da interface e complementam bem a operaçãoBulkInsertAsyncexistente. A consistência na assinatura (uso deICollection<TEntity>eCancellationToken) está adequada.InvoiceReminder.Data/Repository/BaseRepository.cs (1)
42-45: Implementação de BulkRemoveAsync está correta.O método delega apropriadamente para
BulkDeleteAsyncdo EFCore.BulkExtensions, seguindo o padrão estabelecido no repositório.InvoiceReminder.IntegrationTests/Data/Repository/BaseRepositoryIntegrationTests.cs (4)
280-293: Teste de coleção vazia agora determinístico!Excelente correção! O teste agora garante um estado vazio determinístico usando
BulkRemoveAsync(linhas 284-285) antes de validar queGetAll()retorna uma coleção vazia. Isso resolve completamente o problema apontado na revisão anterior.
47-582: Cobertura de testes abrangente e bem estruturada!Os testes de integração estão muito bem organizados e cobrem todos os métodos do repositório de forma completa:
- Testes de
AddAsync,BulkInsertAsync,GetByIdAsync,GetAllcom validações apropriadas- Testes de
RemoveeUpdateverificando tanto o estado doDbContextquanto a persistência no banco- Testes de
Wherecom predicados simples e complexos- Testes de
Disposegarantindo liberação adequada de recursos- Inclusão de testes de cancelamento (
CancellationToken)A estrutura Arrange-Act-Assert está clara e consistente em todos os testes.
23-34: TestInitialize configurado corretamente.A inicialização dos recursos de teste está adequada, criando o
DbContext, repositórios eUnitOfWorknecessários. O uso deNSubstitutepara mockarILogger<UnitOfWork>é apropriado para testes de integração focados em persistência.
588-597: Helper method útil para isolamento de testes.O método
CreateFreshRepository<T>()é útil para criar repositórios com contextos frescos, ajudando a garantir que os testes leiam dados diretamente do banco e não de caches doDbContext.
Enhances test reliability by ensuring a clean state before each test execution. Updates test data generation to provide more realistic values, especially for dates, improving the accuracy of tests related to temporal data. Improves assertion clarity and correctness in entity configuration tests.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (4)
InvoiceReminder.UnitTests.API/AuthenticationSetup/BearerSecuritySchemeTransformerTests.cs (1)
52-52: Considere usarShouldContainKeypara melhor idiomaticidade do Shouldly.A asserção funciona corretamente, mas pode ser mais expressiva usando o método de extensão
ShouldContainKeydo Shouldly, que é mais idiomático para verificar chaves em dicionários.🔎 Refatoração sugerida
- _document.Components.SecuritySchemes.ContainsKey("Bearer").ShouldBe(true); + _document.Components.SecuritySchemes.ShouldContainKey("Bearer");InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/UserConfigTests.cs (1)
51-56: Adicione asserção para o valor padrão do TelegramChatId.A configuração
UserConfigdefine.HasDefaultValue(0)para a propriedadeTelegramChatId, mas o teste não verifica esse valor padrão. Adicione uma asserção para garantir cobertura completa da configuração.🔎 Sugestão de asserção adicional
telegramChatIdProperty.GetColumnName().ShouldBe("telegram_chat_id"); telegramChatIdProperty.GetColumnType().ShouldBe("bigint"); telegramChatIdProperty.IsNullable.ShouldBeFalse(); + telegramChatIdProperty.GetDefaultValue().ShouldBe(0L);InvoiceReminder.IntegrationTests/Data/Repository/BaseRepositoryIntegrationTests.cs (2)
116-127: Considere validação mais rigorosa dos timestamps.O teste verifica apenas que
CreatedAteUpdatedAtnão são valores padrão, mas não confirma que foram definidos com valores recentes. Para maior precisão, você poderia validar que os timestamps estão próximos deDateTime.UtcNow.🔎 Sugestão de validação mais rigorosa
[TestMethod] public async Task BulkInsertAsync_Should_Set_CreatedAt_And_UpdatedAt() { // Arrange var users = TestData.UserFaker().Generate(3); + var beforeInsert = DateTime.UtcNow.AddSeconds(-1); // Act _ = await _userRepository.BulkInsertAsync(users, TestContext.CancellationToken); + var afterInsert = DateTime.UtcNow.AddSeconds(1); // Assert - users.ShouldAllBe(u => u.CreatedAt != default && u.UpdatedAt != default); + users.ShouldAllBe(u => + u.CreatedAt >= beforeInsert && u.CreatedAt <= afterInsert && + u.UpdatedAt >= beforeInsert && u.UpdatedAt <= afterInsert); }
227-251: Teste funciona, mas a asserção poderia ser mais determinística.Linha 249 usa
ShouldBeGreaterThanOrEqualTo(3), o que significa que o teste passa mesmo se houver mais de 3 usuários no banco (de outros testes). Embora isso seja aceitável para testes de integração, considere limpar os dados antes do teste se precisar de maior precisão.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
InvoiceReminder.IntegrationTests/Data/Repository/BaseRepositoryIntegrationTests.csInvoiceReminder.IntegrationTests/Data/Utils/TestData.csInvoiceReminder.UnitTests.API/AuthenticationSetup/BearerSecuritySchemeTransformerTests.csInvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/EmailAuthTokenConfigTests.csInvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/InvoiceConfigTests.csInvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/JobScheduleConfigTests.csInvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/ScanEmailDefinitionConfigTests.csInvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/UserConfigTests.cs
🚧 Files skipped from review as they are similar to previous changes (4)
- InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/InvoiceConfigTests.cs
- InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/EmailAuthTokenConfigTests.cs
- InvoiceReminder.IntegrationTests/Data/Utils/TestData.cs
- InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/ScanEmailDefinitionConfigTests.cs
🧰 Additional context used
🧬 Code graph analysis (2)
InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/JobScheduleConfigTests.cs (2)
InvoiceReminder.Data/Persistence/EntitiesConfig/JobScheduleConfig.cs (2)
JobScheduleConfig(10-44)Configure(12-43)InvoiceReminder.Domain/Entities/JobSchedule.cs (1)
JobSchedule(3-7)
InvoiceReminder.IntegrationTests/Data/Repository/BaseRepositoryIntegrationTests.cs (5)
InvoiceReminder.IntegrationTests/Data/ContainerSetup/DatabaseFixture.cs (2)
Task(44-51)Task(53-62)InvoiceReminder.Data/Repository/BaseRepository.cs (10)
BaseRepository(8-109)BaseRepository(15-20)Dispose(94-102)Dispose(104-108)Task(22-27)Task(29-40)Task(42-45)Task(47-55)Task(67-70)Remove(57-65)InvoiceReminder.Data/Interfaces/IBaseRepository.cs (6)
Task(7-7)Task(8-8)Task(9-9)Task(10-10)Task(12-12)Remove(11-11)InvoiceReminder.IntegrationTests/Data/Utils/TestData.cs (1)
TestData(7-86)InvoiceReminder.Domain/Extensions/EntityExtensions.cs (1)
Guid(41-52)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (csharp)
🔇 Additional comments (15)
InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/JobScheduleConfigTests.cs (1)
1-72: Excelente implementação do teste de configuração!O teste valida de forma abrangente toda a configuração da entidade
JobSchedule, incluindo:
- Mapeamento da tabela
- Chave primária
- Todas as propriedades com seus tipos de coluna, nomes, restrições de nulidade e comprimentos máximos
- Geração de valor para a propriedade
IdNota importante: A validação de
MaxLengthparaCronExpression(linha 55) que estava faltando no comentário de revisão anterior foi corretamente implementada, garantindo cobertura completa da configuração.A estrutura do teste está clara e bem organizada, com comentários separando cada seção de validação, facilitando a manutenção.
InvoiceReminder.UnitTests.API/AuthenticationSetup/BearerSecuritySchemeTransformerTests.cs (1)
8-8: Reorganização do namespace aprovada.A mudança do namespace melhora a clareza e organização da estrutura de testes. O atributo
InternalsVisibleToemBearerSecuritySchemeTransformer.csfoi corretamente atualizado paraInvoiceReminder.UnitTests.API, permitindo acesso adequado aos membros internos pelo projeto de testes.InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/UserConfigTests.cs (3)
1-21: Estrutura do teste está correta!A configuração do teste está bem organizada. O uso de um
ConventionSetvazio é uma prática adequada para testes unitários de configurações EF Core, pois isola as configurações explícitas sem interferência das convenções padrão.
23-49: Validações de tabela, chave primária e índice estão completas!As asserções para nome da tabela, chave primária, índice único no Email e propriedade Id estão corretas e abrangentes.
58-92: Validações das propriedades restantes estão corretas!As asserções para Name, Email, Password, CreatedAt e UpdatedAt validam corretamente os nomes de colunas, tipos, comprimentos máximos e nulabilidade conforme a configuração. Os comentários em português também facilitam a leitura do teste.
InvoiceReminder.IntegrationTests/Data/Repository/BaseRepositoryIntegrationTests.cs (10)
23-43: Configuração e limpeza de recursos estão corretas.A inicialização cria os recursos necessários (DbContext, repositórios, UnitOfWork) e o TestCleanup garante a liberação adequada de todos os recursos na ordem correta.
47-97: Testes de AddAsync cobrem os cenários essenciais.Os testes verificam corretamente o estado da entidade, a persistência após SaveChanges e o valor de retorno. A criação de um contexto novo para verificar a persistência é uma boa prática.
176-221: Testes de GetByIdAsync estão completos e corretos.Boa cobertura incluindo caso de sucesso, ID inexistente e tratamento de cancelamento.
280-293: Teste agora valida corretamente o cenário de coleção vazia!O teste foi significativamente melhorado em relação à versão anterior:
- Remove explicitamente todas as invoices antes do teste (linha 285)
- Valida corretamente que o resultado está vazio usando
ShouldBeEmpty()(linha 292)- Garante uma condição determinística em vez de assumir que o banco está vazio
Isso resolve completamente a preocupação levantada na revisão anterior.
299-354: Testes de Remove cobrem todos os cenários importantes.Boa cobertura incluindo marcação de estado, persistência de deleção e tratamento de entidades desanexadas.
360-439: Testes de Update estão completos e corretos.Excelente cobertura incluindo marcação de estado, persistência de alterações, tratamento de entidades desanexadas e verificação do valor de retorno.
445-514: Testes de Where cobrem bem os cenários de filtragem.Linha 476 mostra uma boa prática ao limpar todos os usuários antes do teste para garantir resultados determinísticos. Boa cobertura de predicados simples, múltiplas correspondências, e resultados vazios.
516-539: Teste de predicados complexos está correto.O teste verifica adequadamente que o método Where suporta predicados compostos com múltiplas condições (
&&).
545-584: Testes de Dispose verificam corretamente o gerenciamento de recursos.Os testes cobrem tanto a liberação de recursos (verificando que ObjectDisposedException é lançada após dispose) quanto a segurança de múltiplas chamadas a Dispose.
590-599: Método auxiliar está bem implementado.O helper
CreateFreshRepository<T>encapsula corretamente a lógica de criação de um novo contexto e repositório, permitindo flexibilidade com o parâmetro genérico.
Refactors tests to use more reliable and accurate assertions. This change addresses potential issues with date comparisons in integration tests by asserting that timestamps fall within an acceptable range, preventing failures due to slight timing differences. Additionally, it strengthens assertions in other tests by using more specific checks (e.g., ShouldContainKey instead of ContainsKey) and adjusting expected counts to be more flexible.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/UserConfigTests.cs (1)
59-78: Considere verificar os tipos de coluna para propriedades string.As asserções para
Name,Passwordverificam o nome da coluna, comprimento máximo e nulabilidade, mas não verificam o tipo de coluna no banco de dados.Como
UserConfignão define explicitamente o tipo de coluna para estas propriedades (apenas o comprimento máximo), o tipo real depende do provedor do banco de dados. Se a intenção é que estas colunas sejam mapeadas para um tipo específico (comovarchar(255)outext), considere adicionar asserções paraGetColumnType()similar ao que é feito para outras propriedades.🔎 Exemplo de asserção adicional
// Verifica propriedade Name var nameProperty = entityType.FindProperty(nameof(User.Name)); _ = nameProperty.ShouldNotBeNull(); nameProperty.GetColumnName().ShouldBe("name"); +nameProperty.GetColumnType().ShouldNotBeNullOrWhiteSpace(); // ou .ShouldBe("character varying(255)") se quiser ser específico nameProperty.GetMaxLength().ShouldBe(255); nameProperty.IsNullable.ShouldBeFalse();
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
InvoiceReminder.IntegrationTests/Data/Repository/BaseRepositoryIntegrationTests.csInvoiceReminder.UnitTests.API/AuthenticationSetup/BearerSecuritySchemeTransformerTests.csInvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/UserConfigTests.cs
🚧 Files skipped from review as they are similar to previous changes (2)
- InvoiceReminder.UnitTests.API/AuthenticationSetup/BearerSecuritySchemeTransformerTests.cs
- InvoiceReminder.IntegrationTests/Data/Repository/BaseRepositoryIntegrationTests.cs
🧰 Additional context used
🧬 Code graph analysis (1)
InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/UserConfigTests.cs (1)
InvoiceReminder.Data/Persistence/EntitiesConfig/UserConfig.cs (2)
UserConfig(10-59)Configure(12-58)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: build
- GitHub Check: Analyze (csharp)
🔇 Additional comments (2)
InvoiceReminder.UnitTests.Infrastructure/Data/EntitiesConfig/UserConfigTests.cs (2)
23-41: Excelente cobertura de tabela, chave primária e índices!As asserções validam corretamente:
- Nome da tabela
- Existência e estrutura da chave primária
- Configuração do índice único no Email com nome do banco de dados
A abordagem de verificar o índice usando
FirstOrDefaultcom predicado é robusta e evita dependências na ordem dos índices.
80-92: Boa validação das propriedades herdadas!As asserções para
CreatedAteUpdatedAtverificam corretamente:
- Nomes das colunas mapeadas
- Tipo específico do PostgreSQL (
timestamp with time zone)- Nulabilidade
Os comentários indicando que estas propriedades são herdadas de
EntityDefaultsadicionam contexto útil para futuros mantenedores.
Refactors the test suite by reorganizing and renaming test projects to improve clarity and maintainability.
Also, integrates Testcontainers for more robust integration tests, ensuring reliable database interactions and adds Docker layer caching in CI to speed up workflow execution.
Summary by CodeRabbit
New Features
Tests
Refactor
Chores
✏️ Tip: You can customize this high-level summary in your review settings.