Unit Test Entity Framework

Tested with:
.Net Framework 4.5
Entity Framework 6.2.0
Moq 4.13.1
MSTest 1.3.2

Github repository here.

This is a demo of how to write unit tests for Entity Framework.
This demo is based on Microsoft article.
It consists of testing EF query and non-query scenarios on both async and non-async calls.

The entity model looks like this.

2019-12-23 14_20_09-Infinity - Microsoft Visual Studio

The data access class look like this.

public class InfinityDataAccess
{
    private readonly InfinityEntities dbContext;
    public InfinityDataAccess(InfinityEntities dbContext)
    {
        this.dbContext = dbContext;
    }

    public IEnumerable<Misc> GetMisc()
    {
        using (this.dbContext)
        {
            return this.dbContext.Misc
                .Select(o => o)
                .ToList();
        }
    }

    public async Task<IEnumerable<Misc>> GetMiscAsync()
    {
        using (this.dbContext)
        {
            return await this.dbContext.Misc
                .Select(o => o)
                .ToListAsync();
        }
    }

    public bool InsertMisc(string data, string description)
    {
        try
        {
            using (this.dbContext)
            {
                var newModel = new Misc
                {
                    Data = data,
                    Description = description
                };

                this.dbContext.Misc.Add(newModel);
                this.dbContext.SaveChanges();
                return true;
            }
        }
        catch (Exception ex)
        {
            return false;
        }
    }

    public async Task<bool> InsertMiscAsync(string data, string description)
    {
        try
        {
            using (this.dbContext)
            {
                var newModel = new Misc
                {
                    Data = data,
                    Description = description
                };

                this.dbContext.Misc.Add(newModel);
                await this.dbContext.SaveChangesAsync();
                return true;
            }
        }
        catch (Exception ex)
        {
            return false;
        }
    }

    public bool UpdateMisc(int miscId, string data, string description)
    {
        try
        {
            using (this.dbContext)
            {
                var dataModel = this.dbContext.Misc.Find(miscId);

                if (dataModel != null)
                {
                    dataModel.Data = data;
                    dataModel.Description = description;
                    this.dbContext.SaveChanges();
                }

                return true;
            }
        }
        catch (Exception ex)
        {
            return false;
        }
    }

    public async Task<bool> UpdateMiscAsync(int miscId, string data, string description)
    {
        try
        {
            using (this.dbContext)
            {
                var dataModel = await this.dbContext.Misc.FindAsync(miscId);

                if (dataModel != null)
                {
                    dataModel.Data = data;
                    dataModel.Description = description;
                    await this.dbContext.SaveChangesAsync();
                }

                return true;
            }
        }
        catch (Exception ex)
        {
            return false;
        }
    }

    public bool DeleteMisc(int miscId)
    {
        try
        {
            using (this.dbContext)
            {
                var dataModel = this.dbContext.Misc.Find(miscId);

                if (dataModel != null)
                {
                    this.dbContext.Misc.Remove(dataModel);
                    this.dbContext.SaveChanges();
                }

                return true;
            }
        }
        catch (Exception ex)
        {
            return false;
        }
    }

    public async Task<bool> DeleteMiscAsync(int miscId)
    {
        try
        {
            using (this.dbContext)
            {
                var dataModel = await this.dbContext.Misc.FindAsync(miscId);

                if (dataModel != null)
                {
                    this.dbContext.Misc.Remove(dataModel);
                    await this.dbContext.SaveChangesAsync();
                }

                return true;
            }
        }
        catch (Exception ex)
        {
            return false;
        }
    }
}

For query scenario on non-async call, it is pretty straight forward.

[TestMethod]
public void TestGetMisc()
{
    // Data to be returned
    var data = new List();
    data.Add(new Misc { Data = "Data1", Description = "Description1" });
    data.Add(new Misc { Data = "Data2", Description = "Description2" });
    data.Add(new Misc { Data = "Data3", Description = "Description3" });

    // Create mock data
    var mockData = new Mock();
    mockData.As().Setup(m => m.Provider).Returns(data.AsQueryable().Provider);
    mockData.As().Setup(m => m.Expression).Returns(data.AsQueryable().Expression);
    mockData.As().Setup(m => m.ElementType).Returns(data.AsQueryable().ElementType);
    mockData.As().Setup(m => m.GetEnumerator()).Returns(data.AsQueryable().GetEnumerator());

    // Create mock EF context
    var mockContext = new Mock();
    mockContext
        .Setup(mock => mock.Misc)
        .Returns(mockData.Object);

    // Assert
    var dataAccess = new InfinityDataAccess(mockContext.Object);
    var result = dataAccess.GetMisc();
    Assert.IsNotNull(result);
    Assert.AreEqual(3, result.Count());
    Assert.AreEqual("Description1", result.FirstOrDefault(o => o.Data == "Data1").Description);
}

The test for query scenario creates mock data of queried EF entity model and setup the mock’s Provider, Expression, ElementType and Enumerator. The return object of the setup are the correspondent properties of the returned data which is a type of IQueryable (see // Create mock data in the code above).
Next, the test creates mock of EF context. The mock is setup to return mock data we created earlier (see // Create mock EF context in the code above).

For non-query scenario on non-async call, it is almost similar to query scenario.

[TestMethod]
public void TestInsertMisc()
{
    // Data to be returned
    var data = new Mock();

    // Create mock EF context
    var mockContext = new Mock();
    mockContext
        .Setup(mock => mock.Misc)
        .Returns(data.Object);

    // Assert
    var dataAccess = new InfinityDataAccess(mockContext.Object);
    var result = dataAccess.InsertMisc("UnitTestData1", "UnitTestDescription1");
    Assert.IsTrue(result);
    mockContext.Verify(m => m.Misc.Add(It.IsAny()), Times.Once);
    mockContext.Verify(m => m.SaveChanges(), Times.Once);
}

The test creates mock data of EF entity model, but it is not necessary to setup the mock’s Provider, Expression, ElementType or Enumerator.
Next, the test creates mock of EF context (see // Create mock EF context in the code above).

For async calls, there are additional helper classes we need to create.
These classes are in-memory query provider to process async requests. We use custom query provider because EF use LINQ extension methods for async calls and these methods are designed to be used only with EF. If we try to use them with our unit tests, it will throw errors.
The 3 classes we need to create are:

  1. DbAsyncQueryProvider
  2. DbAsyncEnumerable
  3. DbAsyncEnumerator

With these helper classes, we can create mock data capable of in-memory async calls. This is the generic method to create the mock data.

private Mock GenerateMockDbSet(IQueryable mockData)
    where T : class
{
    var mock = new Mock();
    mock.As()
        .Setup(x => x.GetAsyncEnumerator())
        .Returns(new TestDbAsyncEnumerator(mockData.GetEnumerator()));

    mock.As()
        .Setup(x => x.Provider)
        .Returns(new TestDbAsyncQueryProvider(mockData.Provider));

    mock.As()
        .Setup(x => x.Expression)
        .Returns(mockData.Expression);

    mock.As()
        .Setup(x => x.ElementType)
        .Returns(mockData.ElementType);

    mock.As()
        .Setup(x => x.ElementType)
        .Returns(mockData.ElementType);

    return mock;
}

So for query scenario on async call, we just call the above method to create mock data for us.

[TestMethod]
public async Task TestGetMiscAsync()
{
    // Data to be returned
    var data = new List();
    data.Add(new Misc { Data = "Data1", Description = "Description1" });
    data.Add(new Misc { Data = "Data2", Description = "Description2" });
    data.Add(new Misc { Data = "Data3", Description = "Description3" });

    // Create mock data
    var mockData = GenerateMockDbSet(data.AsQueryable());

    // Create mock EF context
    var mockContext = new Mock();
    mockContext
        .Setup(mock => mock.Misc)
        .Returns(mockData.Object);

    // Assert
    var dataAccess = new InfinityDataAccess(mockContext.Object);
    var result = await dataAccess.GetMiscAsync();
    Assert.IsNotNull(result);
    Assert.AreEqual(3, result.Count());
    Assert.AreEqual("Description1", result.FirstOrDefault(o => o.Data == "Data1").Description);
}

There are more sample tests on the github repository to demonstrate every single scenarios in both async and non-async calls.

DynamicProxyGenAssembly2

DynamicProxyGenAssembly2 is a temporary assembly built by mocking systems that use CastleProxy like Moq or NSubsitute. It is generated when the mock is needed and disposed of after the tests are finished.

Tested on:
Moq 4.10 https://github.com/moq/moq4
.Net 4.5

Following is AssemblyInfo.cs in QC.Client project.

using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

[assembly: AssemblyTitle("QC.Client")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("QC.Client")]
[assembly: AssemblyCopyright("Copyright ©  2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]

[assembly: Guid("d62d1a60-782a-46d8-b5f5-2f6d12ad1339")]

[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: InternalsVisibleTo("QC.ClientTest")]

Following is class i want to test.
UserManagement.cs (In QC.Client project)

namespace QC.Client
{
    public class UserManagement
    {
        public void UpdateUser(string address)
        {
            var executer = new Executer();
            executer.Run();
        }
    }
}

Executer.cs (In QC.Client project)

namespace QC.Client
{
    public class Executer
    {
        internal virtual bool Run()
        {
            return true;
        }
    }
}

Following is my unit test.
UserManagementTest.cs (In QC.ClientTest project)

using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using QC.Client;

namespace QC.ClientTest
{
    [TestClass]
    public class UserManagementTest
    {
        [TestMethod]
        public void UpdateUserShouldWork()
        {
            // Mock
            var mock = new Mock();
            mock.Setup(x => x.Run());

            // Act
            var userManagement = new UserManagement();
            userManagement.UpdateUser("Test Address");

            // Assert
            mock.Verify(x => x.Run(), Times.Once);
        }
    }
}

Problem
MS Test throwing following error when unit testing internal member of a class in different project.
When unit test in above `UserManagementTest.cs` is run, MS Test throw following error:

Message: Test method QC.ClientTest.UserManagementTest.UpdateUserShouldWork threw exception:
System.ArgumentException: Cannot set up Executer.Run because it is not accessible to the proxy generator used by Moq:
Can not create proxy for method Boolean Run() because it or its declaring type is not accessible. Make it public, or internal and mark your assembly with [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] attribute, because assembly QC.Client is not strong-named.

Note:
– MS Test only throw exception if the accessor of method being tested is internal. In above example it is `Executer.Run()`.
– Virtual keyword in method being tested is to allow Moq to mock the method.

Solution is to simply add following code in AssemblyInfo.cs

[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]

Sources
Stackoverflow

Unit Test Internal Members

Applies to .Net application in Visual Studio 2010 and up.

Say I have C# project (call it QC project). In the project, I have class that has internal member(s) like this:

namespace QC
{
    public class PersonService
    {
        public bool PromotePerson(string userName)
        {
        }

        internal bool FindPerson(string userName)
        {
        }
    }
}

For unit test, I’d created separate project (call it QCTest project). Because internal members can only be accessed in same assembly, I won’t be able to invoke `QC.PersonService.FindPerson(string userName)` method from QCTest project.

To overcome this issue, in `AssemblyInfo.cs` of project being tested (in my case, QC project), simply add

[assembly: InternalsVisibleTo("QCTest")]

After rebuilding my solution, I am able to access `QC.PersonService.FindPerson(string userName)` in my QCTest project.

As an added bonus, if you use mock library like Moq or Rhino and try to mock internal members, you most likely need to add:

[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]

What is `DynamicProxyGenAssembly2` ?

DynamicProxyGenAssembly2 is a temporary assembly built by mocking systems that use CastleProxy like Moq or NSubsitute. It is generated when the mock is needed and disposed of after the tests are finished.

Reference: https://stackoverflow.com/a/17179923

Unit Testing DTO Classes

Reason why I unit test my DTO (Data Transfer Object) classes are because I pass these classes to client app and client app might use them and expect certain properties in response. Sometimes I change DTO properties that I used in client app and forget to refactor client app.
By unit testing my DTO classes, it acts as reminder for me to refactor client app whenever DTO properties (or its name) changes.

For example, I have Person DTO.

Person.cs

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Age { get; set; }
}

To unit test, I would create PersonMirror DTO.

public class PersonMirror
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Age { get; set; }
}

Then use following helper class to unit test my DTO.

public class TestHelper
{
    public static void CompareType()
    {
        var errorMessage = "Type: {0}; Property: {1}";

        var instance = Activator.CreateInstance(typeof(T));
        var instanceType = instance.GetType();
        var mirror = Activator.CreateInstance(typeof(TMirror));
        var mirrorType = mirror.GetType();
        var mirrorProperties = mirrorType.GetProperties();

        // Remove 'Mirror' convention
        var mirrorTypeName = mirrorType.Name;
        if (mirrorType.Name.IndexOf("Mirror") > 0)
        {
            mirrorTypeName = mirrorType.Name.Substring(0, mirrorType.Name.IndexOf("Mirror"));
        }

        // Compare type name
        Assert.AreEqual(mirrorTypeName, instanceType.Name);

        // Compare properties
        foreach (var mirrorProperty in mirrorProperties)
        {
            var instanceProperty = instanceType.GetProperty(mirrorProperty.Name);

            Assert.IsNotNull(instanceProperty, string.Format(errorMessage, instanceType.FullName, mirrorProperty.Name));
        }
    }
}

Usage (using MS Test):
PersonTest.cs

[TestClass]
public class PersonTest
{
    [TestMethod]
    public void TestPersonDto()
    {
        TestHelper.CompareType<Person, PersonMirror>();
    }    
}

Karma: Only Run 1 Test

Useful hack to only run 1 test in Karma.

Instead of ‘it’, change test declaration to ‘fit’.
Example:

    fit('should create', () => {
        expect(component).toBeTruthy();
    });

This will force Karma to only run ‘should create’ test.

Mocking Generic Method with NSubstitute

The generic method:


public interface ICacheService
{
    T Get<T>(string id);
}

User object in NSubstitute to mock the generic method.


private ICacheService MockICacheService()
{
    var service = Substitute.For<ICacheService>();

    // Return Models
    object returnForAny = null;

    // Mock
    service.Get<object>(Arg.Any<string>()).ReturnsForAnyArgs(returnForAny);

    return service;
}

Return Null in NSubstitute Mock Framework

The API is not intuitive, at least not for me. So, I have to figure out how to return null with this mocking framework I have never used before.

var service = Substitute.For<ISomethingService>();

// Mock
service.Get<IEnumerable<SomeDomain>>(Arg.Any<string>()).ReturnsForAnyArgs(x => null);

Normally, I would just to .ReturnsForAnyArgs(null), not the case with NSubstitute.

Unit Testing WIF’s ClaimsPrincipalPermission.CheckAccess

WIF 4.5 has ClaimsPrincipalPermission.CheckAccess method, very useful to check user’s authorization. You can use this as method call or attribute.

// Imperative method call
using System.IdentityModel.Services;
public ActionResult Index()
{
    ClaimsPrincipalPermission.CheckAccess("foo", "bar");

    return View();
}

// Attribute
[ClaimsPrincipalPermission(SecurityAction.Demand, Operation="foo", Resource="bar")]
public ActionResult ViewFoobar()
{
    return View();
}

Either way, how do we unit test this? My approach is to first abstract out ClaimsPrincipalPermission and create a new wrapper class that will be injected to the dependent class.

Abstract Out

using System.IdentityModel.Services;

public class ClaimsPrincipalWrapper : IClaimsPrincipalWrapper
{
    public void CheckAccess(string resource, string action)
    {
        ClaimsPrincipalPermission.CheckAccess(resource, action);
    }
}

Dependency Injection

using System.IdentityModel.Services;

public class HomeController : Controller
{
    private readonly IClaimsPrincipalWrapper _ClaimsPrincipalWrapper;

    public HomeController(IClaimsPrincipalWrapper claimsPrincipalWrapper)
    {
        _ClaimsPrincipalWrapper = claimsPrincipalWrapper;
    }

    public ActionResult Index()
    {
        _ClaimsPrincipalWrapper.CheckAccess("foo", "bar");

        return View();
    }
}

Unit Test

[TestMethod]
public void TestIndex()
{
    // Arrange
    var _claimsPrincipal = new Mock<IClaimsPrincipalWrapper>();
    _claimsPrincipal.Setup(m => m.CheckAccess(It.IsAny<string>, It.IsAny<string>));
    var _controller = new HomeController(_claimsPrincipalMock.Object);

    // Act
    var _result = _controller.Index() as ViewResult;

    // Assert
    Assert.IsTrue(_result.View != null);
}

Visual Studio 2012: Debugging Unit Tests Doesn’t Work

There’s a problem in Visual Studio 2012 where debugging unit tests doesn’t work. This often happens when you enable code coverage.

The solution is fairly simple, un-check any selected test setting file under Test > Test Settings.

This behavior is expected, at least according to Microsoft, they just don’t support debugging for code coverage.

Guide to Testable Code

If you haven’t already, go learn unit testing and write testable code. I promise you, your code will look much better and engineer-like. And not just the look, more importantly it reflects into your application, more robust, higher quality, SOLID. If that’s not enough, it even reflects into yourself and your career, you look more professional and not some ‘just make it work’ developers.

Good guys (and smart, of course) at Google provide easy to understand and simple to follow guide for testable code.
http://misko.hevery.com/code-reviewers-guide/

The e-book is free as well: http://misko.hevery.com/attachments/Guide-Writing%20Testable%20Code.pdf