keelerjr12
keelerjr12

Reputation: 1903

EF Core - Simple unit test of repository pattern

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

Answers (1)

arekzyla
arekzyla

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

Related Questions