Attualmente sto lavorando su un'API Web di ASP.NET Core 2.0 con EF Core 2.0. Ho intenzione di implementare il pattern Repository + UnitOfWork e ho già creato le astrazioni, le interfacce, ecc. Dal momento che sto seguendo un approccio TDD, voglio scrivere test su tali interfacce prima di procedere con l'implementazione.
Il problema che sto affrontando è per lo più legato alla semantica. Ho creato due progetti nella mia soluzione, uno per i test unitari e uno per i test di integrazione. È ovvio per me che un test che verifica anche il database non è un test unitario e deve quindi essere inserito nel progetto IntegrationTests. Il fatto è che, sto progettando di utilizzare il provider EntityFrameworkCore.InMemory e avviare un database falso nella memoria per ogni test.
Quindi ogni test dovrebbe avere questa struttura:
[TestClass]
public class GamesRepositoryTest
{
AppDbContext _context;
IGamesRepository _repository;
public GamesRepositoryTest()
{
}
[TestInitialize]
public void Initialize()
{
DbContextOptionsBuilder<AppDbContext> builder = new DbContextOptionsBuilder<AppDbContext>().UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString());
_context = new AppDbContext(builder.Options);
_repository = new GamesRepository(_context);
}
[TestCleanup]
public void Cleanup()
{
_context.Database.EnsureDeleted();
}
}
Quindi la mia domanda è: EntityFrameworkCore.InMemory fornisce un livello adeguato di astrazione in modo che la suddetta classe possa essere considerata un test unitario o dovrei inserirla nel progetto IntegrationTests?
Il nuovo provider in-memory ha confuso il riempimento di tutti. Innanzitutto, chiariamo il suo scopo: è un fornitore di dati di prova. Questo è tutto. Si potrebbe facilmente DbContext
giro DbContext
e restituire un elenco statico o qualcosa del genere. Il provider in-memory ti offre un modo più semplice per configurare lo scaffold del test. Non è appropriato per i test di integrazione, perché in realtà non lo si utilizzerà in produzione. Un corretto test di integrazione potrebbe colpire un vero fac-simile del tuo setup di produzione.
Detto questo, il problema principale con il nuovo provider in-memory per Entity Framework Core è che ora le persone sembrano abusarne per testare cose che non dovrebbero testare. EF Core è già ben testato, quindi è necessario testare solo il codice dell'applicazione. Ancora una volta, basta pensarlo come un mock senza dover effettivamente impostare una simulazione. Finché lo fai, dovresti stare bene.
Sulla base di tutto ciò, per rispondere alla tua domanda, i test dovrebbero essere unit test, se per nessun altro motivo se non stai creando un test di integrazione, non dovresti utilizzare il provider in memoria. Assicurati solo di fare effettivamente dei test unitari.
Se stai provando con un vero dbContext, se sta colpendo un RDBMS o un provider InMemory, è un test di integrazione. Perché? Perché stai testando l'implementazione di questo framework, non il tuo codice in esecuzione nel tuo metodo. I test unitari testano solo la "unità" di codice che stanno eseguendo, in genere un singolo metodo (e non i suoi collaboratori).
Il provider InMemory di EF Core non è al 100% lo stesso del test con un vero database. In effetti, ci sono alcune differenze. È in genere utile l'IME in fase di sviluppo per mostrare come funziona il sistema con alcuni dati di inizializzazione e per test funzionali che possono verificare che tutto il sistema funzioni come previsto (ad esempio, utilizzando TestServer
).
Se il progetto di test unitario deve contenere solo test unitari, non dovrebbe avere alcuna dipendenza dal codice specifico dell'infrastruttura come EF Core. Normalmente dovrebbe avere solo una dipendenza dai propri progetti che sono stati testati e dagli strumenti che si stanno utilizzando per i test (ad esempio xUnit, Moq, ecc.). Se scopri che stai sfruttando le dipendenze dell'infrastruttura, è probabile che tu stia scrivendo test di integrazione.