Vorrei poter testare l'unità nel repository di informazioni ZIPCode con test di unità molto semplici. Mi chiedo come posso farlo? Potrei semplicemente iniettare un DbContext che utilizza un database fittizio (ad esempio RouteMiningTestDB).
Tuttavia, c'è un modo per farlo in memoria? Sto usando EF Core e voglio incapsularlo il più possibile. Inoltre, dovrei iniettare DbContext o una stringa di connessione? Ho visto entrambi usati e non riesco davvero a vedere gli svantaggi di entrambi. Grazie!
RouteMiningBLL.IZIPCodeInfoRepository
namespace RouteMiningBLL
{
public interface IZIPCodeInfoRepository
{
void AddZIPCodeInfo(ZIPCodeInfo zipCodeInfo);
ZIPCodeInfo GetByZIPCode(int zipcode);
void UpdateZIPCodeInfo(ZIPCodeInfo zipCodeInfo);
void DeleteZIPCodeInfo(int zipcode);
}
}
RouteMiningDAL.ZIPCodeInfoRepository
using HtmlAgilityPack;
using Microsoft.EntityFrameworkCore;
using RouteMiningBLL;
using System.Linq;
namespace RouteMiningDAL
{
public class ZIPCodeInfoRepository : IZIPCodeInfoRepository
{
// fix
//private static string ConnectionString = @"Server=(localdb)\MSSQLLocalDB;Database=RouteMiningDB;Trusted_Connection=True;";
//private RouteMiningDataContext db = new RouteMiningDataContext(new DbContextOptionsBuilder().UseSqlServer(ConnectionString).Options);
private RouteMiningDataContext db;
public ZIPCodeInfoRepository(RouteMiningDataContext dbContext)
{
db = dbContext;
}
public void AddZIPCodeInfo(RouteMiningBLL.ZIPCodeInfo zipCodeInfo)
{
db.ZIPCodeInfo.Add(MapBLLToDAL(zipCodeInfo));
db.SaveChanges();
}
public RouteMiningBLL.ZIPCodeInfo GetByZIPCode(int zipcode)
{
var info = db.ZIPCodeInfo.Find(zipcode);
var zipcodeinfo = new RouteMiningBLL.ZIPCodeInfo(info.ZIPCode, info.Population, info.AverageHomeValue, info.HouseHoldIncome, info.MedianAge, info.NumberOfBusinesses, info.NumberOfEmployees);
return zipcodeinfo;
}
public void UpdateZIPCodeInfo(RouteMiningBLL.ZIPCodeInfo zipCodeInfo)
{
throw new System.NotImplementedException();
}
public void DeleteZIPCodeInfo(int zipcode)
{
ZIPCodeInfo info = db.ZIPCodeInfo.Find(zipcode);
db.ZIPCodeInfo.Remove(info);
}
private ZIPCodeInfo MapBLLToDAL(RouteMiningBLL.ZIPCodeInfo zipCodeInfo)
{
var info = new ZIPCodeInfo
{
ZIPCode = zipCodeInfo.ZIPCode,
Population = zipCodeInfo.Population,
AverageHomeValue = zipCodeInfo.AverageHomeValue,
HouseHoldIncome = zipCodeInfo.HouseHoldIncome,
MedianAge = zipCodeInfo.MedianAge,
NumberOfBusinesses = zipCodeInfo.NumberOfBusinesses,
NumberOfEmployees = zipCodeInfo.NumberOfEmployees
};
return info;
}
}
}
È possibile utilizzare il provider di database InMemory in EF Core.
Quindi in pratica puoi fare qualcosa del genere:
var options = new DbContextOptionsBuilder<RouteMiningDataContext>()
.UseInMemoryDatabase(databaseName: "database_test_name")
.Options;
using (var context = new RouteMiningDataContext(options))
{
//your test
}
Perché funzioni devi aggiungere un tale costruttore per il tuo DbContext:
public RouteMiningDataContext(DbContextOptions<RouteMiningDataContext> : base(options)
{ }
E imposta la stringa di connessione in modo che Database sia impostato su EFProviders.InMemory:
"Server=(localdb)\MSSQLLocalDB;Database=EFProviders.InMemory;Trusted_Connection=True;"
NOTA: il provider InMemory non imita SQL Server in tutti gli aspetti, quindi fai attenzione
Puoi scaricarlo da qui: https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.InMemory/
Per maggiori informazioni: https://docs.microsoft.com/en-us/ef/core/miscellaneous/testing/in-memory