EF Core - 存储库模式的简单单元测试

时间:2018-03-18 23:50:52

标签: c# tdd entity-framework-core

我希望能够通过非常简单的单元测试对ZIPCode Info Repository进行单元测试。我想知道如何做到这一点?我可以注入一个使用模拟数据库的DbContext(例如RouteMiningTestDB)。

但是,有什么方法可以在内存中做到这一点吗?我使用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;
        }
    }
}

1 个答案:

答案 0 :(得分:1)

您可以在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 Server,因此请注意

您可以从此处下载:https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.InMemory/

了解更多信息:https://docs.microsoft.com/en-us/ef/core/miscellaneous/testing/in-memory