Ho una funzione che chiama una stored procedure con Entity Framework:
public async Task<List<Entity>> GetEntity(int id)
{
var param = new SqlParameter("@id", id);
return await myContext.Database
.SqlQuery<MyEntity>("[myStoredProcedure] @id", param)
.ToListAsync();
}
E vorrei creare un test unitario usando Effort. Ho già uno sforzo (e un database NMemory) per simulare un database (basato sul mio contesto), su Initialize
per ogni Unit Test, come:
[TestInitialize]
public void Initialize()
{
Effort.Provider.EffortProviderConfiguration.RegisterProvider();
EffortProviderFactory.ResetDb()
using (var context = new MyContext("PWET"))
{
context.Database.CreateIfNotExists();
context.Constructeurs.Add(new Constructeur { Nom = "Zebra" });
context.Constructeurs.Add(new Constructeur { Nom = "Joya" });
context.SaveChanges();
}
}
Dove EffortProviderFactory
è:
public class EffortProviderFactory : IDbConnectionFactory
{
private static DbConnection _connection;
private readonly static object _lock = new object();
public static void ResetDb(){
lock (_lock){
_connection = null;
}
}
public DbConnection CreateConnection(string nameOrConnectionString)
{
lock (_lock){
if (_connection == null)
_connection = Effort.DbConnectionFactory.CreateTransient();
return _connection;
}
}
}
Ho provato ad aggiungere la creazione della procedura memorizzata in questo modo:
[TestInitialize]
public void Initialize()
{
Effort.Provider.EffortProviderConfiguration.RegisterProvider();
EffortProviderFactory.ResetDb()
using (var context = new MyContext("PWET"))
{
context.Database.CreateIfNotExists();
context.Database.ExecuteSqlCommand(@"
CREATE PROCEDURE [dbo].[myStoredProcedure]
@id INT = 0
AS
BEGIN
SELECT foo
FROM bar
WHERE foo.Id = @id
ORDER BY foo.Id;
END");
}
}
Ma lancia una NotSupportedException
. Come posso fare, e qual è il modo migliore?
Lo sforzo è un provider di database in-memory basato su file che fornisce un'istanza di DbContext
con un database temporaneo di proprietà privata: nuovo contesto, nuovo database, nessuna interazione di test. Questa è la parte buona.
Lo svantaggio, ovviamente, è che non è - e mai lo sarà - un vero e proprio motore di database. Pertanto non supporterà mai le stored procedure scritte in nessuno dei comuni dialetti SQL (come t-SQL o PL-SQL). Per quanto riguarda lo sforzo (cioè NMemory) ha stored procedure, è semplicemente un IQueryable
memorizzato, come è evidente dal costruttore StoredProcedure
. Notando in remoto le procedure memorizzate t-SQL.
L'unico modo per testare le stored procedure nel codice del livello di accesso ai dati, che è un'ottima idea, è scrivere test di integrazione. Ci sono approssimativamente due approcci per rendere i test di integrazione indipendenti l'uno dall'altro:
Crea / semina un nuovo database per ogni test
Utilizzare un database esistente con casi di test e ripristinare le modifiche dopo ogni test, ad esempio utilizzando TransactionScope .
I test di integrazione non saranno mai così veloci come i test unitari e completano solo i test unitari, ma tuttavia, nella mia pratica di codifica relativa ai livelli di dati, sono diventati cittadini di prima classe nella suite di test. Per me, la correttezza è più importante della velocità.