Reputation: 1903
I would like to be able to unit test the ZIPCode Info Repository with very simple unit tests. I'm wondering how I can do this? I could just inject a DbContext that uses a mock database (e.g. RouteMiningTestDB).
However, is there any way I can do this in-memory? I'm using EF Core and want to encapsulate this as much as possible. Additionally, should I be injecting DbContext or a Connection String? I've seen both used and can't really see disadvantages to either or. Thanks!
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;
}
}
}
Upvotes: 1
Views: 1636
Reputation: 2898
You can use InMemory database provider in EF Core.
So basically you can do something like this:
var options = new DbContextOptionsBuilder<RouteMiningDataContext>()
.UseInMemoryDatabase(databaseName: "database_test_name")
.Options;
using (var context = new RouteMiningDataContext(options))
{
//your test
}
For it to work you need to add such a constructor for your DbContext:
public RouteMiningDataContext(DbContextOptions<RouteMiningDataContext> : base(options)
{ }
And set your connection string to have Database set to EFProviders.InMemory:
"Server=(localdb)\MSSQLLocalDB;Database=EFProviders.InMemory;Trusted_Connection=True;"
NOTE: InMemory provider does not mimic SQL Server in all aspects so be aware
You can download it from here: https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.InMemory/
For more info: https://learn.microsoft.com/en-us/ef/core/miscellaneous/testing/in-memory
Upvotes: 1