Non riesco a verificare e testare il mio database nei provider di memoria. per esempio ho impostato queste proprietà su richiesto:
public abstract class Log
{
#region Properties
public Guid Id { get; set; }
[Required]
public string ClientIp { get; set; }
[Required]
public string Application { get; set; }
[Required]
public string Host { get; set; }
[Required]
public string Path { get; set; }
[Required]
public string Method { get; set; }
[Required]
public string User { get; set; }
[Required]
public string Date { get; set; }
#endregion
}
e questo è il mio DBContext:
public class ApplicationDbContext : IdentityDbContext<ApplicationUsers, Role, Guid>, IUnitOfWork
{
private readonly IConfigurationRoot _configuration;
public ApplicationDbContext(IConfigurationRoot configuration)
{
_configuration = configuration;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var useInMemoryDatabase = _configuration[key: "UseInMemoryDatabase"].Equals(value: "true",
comparisonType: StringComparison.OrdinalIgnoreCase);
if (useInMemoryDatabase)
optionsBuilder.UseInMemoryDatabase();
else
optionsBuilder.UseSqlServer(
connectionString: _configuration[key: "ConnectionStrings:ApplicationDbContextConnection"]
, sqlServerOptionsAction: serverDbContextOptionsBuilder =>
{
var minutes = (int) TimeSpan.FromMinutes(3).TotalSeconds;
serverDbContextOptionsBuilder.CommandTimeout(commandTimeout: minutes);
});
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Log>()
.HasKey(c => c.Id);
modelBuilder.Entity<Log>()
.HasDiscriminator<int>(name: "Type")
.HasValue<LogRequest>(value: Convert.ToInt32(value: LogLevel.Information))
.HasValue<LogError>(value: Convert.ToInt32(value: LogLevel.Error));
}
E questo è il mio test unitario:
[TestClass]
public class LogRepositoryTest
{
private readonly IServiceProvider _serviceProvider;
public LogRepositoryTest()
{
var services = new ServiceCollection();
services.AddScoped<IUnitOfWork, ApplicationDbContext>();
services.AddScoped<ILogRepository, LogRepository>();
services.AddSingleton(provider => new ConfigurationBuilder()
.AddInMemoryCollection(initialData: new[]
{
new KeyValuePair<string, string>(key: "UseInMemoryDatabase", value: "true"),
})
.Build());
services.AddEntityFrameworkInMemoryDatabase().AddDbContext<ApplicationDbContext>(ServiceLifetime.Scoped);
_serviceProvider = services.BuildServiceProvider();
}
[TestMethod]
public async Task Verify_SaveRequestLog()
{
using (var serviceScope = _serviceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
using (var context = serviceScope.ServiceProvider.GetRequiredService<IUnitOfWork>())
{
context.Set<Log>().Add(new LogRequest());
var result =await context.SaveAllChangesAsync();
Assert.AreEqual(1, result);
}
}
}
Ma il metodo di test unitario restituisce sempre 1 e passa, nel frattempo l'oggetto vuoto di LogRequest non deve salvare nulla nel database! Come posso determinare le proprietà non nulle per il test unitario? In effetti, come posso far rispettare il test dell'unità per riflettere sulle politiche di convalida?
Aggiornare:
Basato su questo linke: Entity Framework Core Issues
che ho chiesto, ho avuto questa risposta:
EF Core non esegue alcuna convalida delle entità oltre a quanto necessario per coerenza interna. La convalida è qualcosa che potrebbe essere fatto in EF, ma l'esperienza dimostra che non è qualcosa che è utile a molti sviluppatori perché di solito non può sostituire la convalida lato client o la convalida del database e ci sono anche altri luoghi in cui la validazione può essere eseguita in modo più efficace .
Oltre il database EF, il database in memoria non convalida attualmente il nullability (ovvero la necessità) durante il salvataggio dei valori delle proprietà. Lascerò aperto questo problema in modo che possiamo discutere in gruppo se questo è qualcosa che dovremmo aggiungere.
Inoltre, se l'intento è di test con un database in memoria come un'approssimazione per un database relazionale, è possibile prendere in considerazione l'utilizzo di SQLite in modalità memoria. Vedere https://docs.microsoft.com/en-us/ef/core/miscellaneous/testing/index per ulteriori informazioni.
Basato su questo linke: Entity Framework Core Issues
che ho chiesto, ho avuto la mia risposta:
class MyContext : DbContext
{
public override int SaveChanges()
{
var entities = from e in ChangeTracker.Entries()
where e.State == EntityState.Added
|| e.State == EntityState.Modified
select e.Entity;
foreach (var entity in entities)
{
var validationContext = new ValidationContext(entity);
Validator.ValidateObject(entity, validationContext);
}
return base.SaveChanges();
}
}