1

Im working on a C# Project that uses Entity Framework, Repository-Pattern, UnitOfWork-Pattern and Moq. I´m new to EF and Unit Tests with Moq and got the following problem: I get null pointers, when i try to test the methods from the service class...and it seems as if the context can´t get instantiated. Can anyone point my mistake out or provide me with a link?

Example:

portionService.cs

/// <summary>
/// The PortionService class represents a service for the Portion model.
/// </summary>
public class PortionService : Service, IPortionService
{
    /// <summary>
    /// In this constructor the base constructor of the Service class is called.
    /// </summary>
    /// <param name="context">Represents a context of the data access layer.</param>
    public PortionService(IDALContext context) : base(context) { }

    public void Add(Portion portion)
    {
        context.Portion.Create(portion);
        context.SaveChanges();
    }

    public Portion GetPortionByName(string name)
    {
        return context.Portion.GetAll().Where(p => p.Name.ToUpper() == name.ToUpper()).LastOrDefault();
    }

portionServiceTests.cs

// TestClass for PortionService-Tests
[TestClass]
public class PortionServiceTests
{
    private PortionService _portionService;

    // define the mock object
    private Mock<IPortionService> _portionServiceMock;

    [TestInitialize]
    public void Init()
    {
        _portionService = new PortionService(new DALContext());

        // create the mock object
        _portionServiceMock = new Mock<IPortionService>();
    }[TestMethod]
    public void EnteringPortionNameReturnsThePortion()
    { 
    //arrange
    // arrange data
    Portion portion = new Portion { PortionID = 12, Name = "testPortion" };

    //arrange expectations 
    _portionServiceMock.Setup(service => service.GetPortionByName("testPortion")).Returns(portion).Verifiable();

    //act
    var result = _portionService.GetPortionByName("testPortion");

    //verify
    Assert.AreEqual(portion, result.Name);
    }

DALContext.cs

    public class DALContext : IDALContext, IDisposable
{
    /// <summary>
    /// The _context property represents the context to the current Database.
    /// </summary>
    private DatabaseContext _context;

    private Repository<Portion> _portionRepository;
...
    /// <summary>
    /// In this constructor the single instance of the DataBaseContext gets instantiated.
    /// </summary>
    public DALContext()
    {
        _context = new DatabaseContext();
    }
Frank
  • 1,113
  • 3
  • 14
  • 27
  • After another several hours of research I found [this](http://stackoverflow.com/a/5770206) answer from Mr. Mrnka. It seems as if unit testing services in an architecture like mine is useless and should be covered with integration tests. Any thoughts? – Frank May 25 '13 at 06:51
  • I am 100% agree with this EF guru, don't do test just for the purpose of testing. If it's not testing the actual correctness, it's worthless. – J.W. May 25 '13 at 12:42

2 Answers2

2

it's actually not easy to unit test EF based application. I would recommend using a library like effort to mock the entity framework.

J.W.
  • 17,991
  • 7
  • 43
  • 76
2

You are trying to verify the mock result to an actual data in the database, that's why it fails. Your unit test should test the service, and that the service calls the context, not the mock of the service itself.

The following example uses FakeDbSet approach from Rowan Miller's article.

using System.Data.Entity;
using System.Linq;
using Moq;
using NUnit.Framework;
using SharpTestsEx;

namespace StackOverflowExample.EntityFramework
{
    public class DataEntity
    {
        public int Id { get; set; }
        public string Data { get; set; }
    }

    public interface IContext
    {
        IDbSet<DataEntity> DataEntities { get; }
    }

    public class DataService
    {
        private IContext _db;
        public DataService(IContext context)
        {
            _db = context;
        }

        public DataEntity GetDataById(int id)
        {
            return _db.DataEntities.First(d => d.Id == id);
        }
    }

    [TestFixture]
    public class DataServiceTests
    {
        [Test]
        public void GetDataByIdTest()
        {
            //arrange
            var datas = new FakeDbSet<DataEntity>
                {
                    new DataEntity {Id = 1, Data = "one"},
                    new DataEntity {Id = 2, Data = "two"}
                };
            var context = new Mock<IContext>();
            context.SetupGet(c => c.DataEntities).Returns(datas);
            var service = new DataService(context.Object);

            //act
            var result = service.GetDataById(2);

            //assert
            result.Satisfy(r =>
                           r.Id == 2
                           && r.Data == "two");
        }
    }
} 
Sunny Milenov
  • 21,990
  • 6
  • 80
  • 106
  • There are a lot of good comments in that blog post, I would encourage you to read through them. – J.W. May 24 '13 at 12:22