EF Core - 存储库模式的简单单元测试
EF Core - Simple unit test of repository pattern
我希望能够使用非常简单的单元测试对邮政编码信息存储库进行单元测试。我想知道我该怎么做?我可以注入一个使用模拟数据库(例如 RouteMiningTestDB)的 DbContext。
但是,有什么办法可以在内存中执行此操作吗?我正在使用 EF Core 并希望尽可能地封装它。此外,我应该注入 DbContext 还是连接字符串?我见过两者都用过,但看不出任何一个或的缺点。谢谢!
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;
}
}
}
您可以在 EF Core 中使用 InMemory 数据库提供程序。
所以基本上你可以这样做:
var options = new DbContextOptionsBuilder<RouteMiningDataContext>()
.UseInMemoryDatabase(databaseName: "database_test_name")
.Options;
using (var context = new RouteMiningDataContext(options))
{
//your test
}
要使其正常工作,您需要为 DbContext 添加这样的构造函数:
public RouteMiningDataContext(DbContextOptions<RouteMiningDataContext> : base(options)
{ }
并将连接字符串设置为数据库设置为 EFProviders.InMemory:
"Server=(localdb)\MSSQLLocalDB;Database=EFProviders.InMemory;Trusted_Connection=True;"
注意: InMemory 提供程序不会在所有方面模仿 SQL 服务器,因此请注意
您可以从这里下载:https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.InMemory/
更多信息:https://docs.microsoft.com/en-us/ef/core/miscellaneous/testing/in-memory
我希望能够使用非常简单的单元测试对邮政编码信息存储库进行单元测试。我想知道我该怎么做?我可以注入一个使用模拟数据库(例如 RouteMiningTestDB)的 DbContext。
但是,有什么办法可以在内存中执行此操作吗?我正在使用 EF Core 并希望尽可能地封装它。此外,我应该注入 DbContext 还是连接字符串?我见过两者都用过,但看不出任何一个或的缺点。谢谢!
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;
}
}
}
您可以在 EF Core 中使用 InMemory 数据库提供程序。
所以基本上你可以这样做:
var options = new DbContextOptionsBuilder<RouteMiningDataContext>()
.UseInMemoryDatabase(databaseName: "database_test_name")
.Options;
using (var context = new RouteMiningDataContext(options))
{
//your test
}
要使其正常工作,您需要为 DbContext 添加这样的构造函数:
public RouteMiningDataContext(DbContextOptions<RouteMiningDataContext> : base(options)
{ }
并将连接字符串设置为数据库设置为 EFProviders.InMemory:
"Server=(localdb)\MSSQLLocalDB;Database=EFProviders.InMemory;Trusted_Connection=True;"
注意: InMemory 提供程序不会在所有方面模仿 SQL 服务器,因此请注意
您可以从这里下载:https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.InMemory/
更多信息:https://docs.microsoft.com/en-us/ef/core/miscellaneous/testing/in-memory