1

Trying to Mock my EF Context which is coupled to my Repository. Im using Moq, trying to setup a mocked Context and pass it into the Repository by the constructor.

After that Im calling the Add method, to simply add a new object which I after that try to Assert by checking if the context i passed in has changed state...

Error Im getting is a NullReference Exception and I guess its because my mocking isn't correct..

This is the code:

Test with not working mock

[TestClass]
public class GameRepositoryTests
{
    [TestMethod]
    public void PlayerThatWonMustBeAddedToTopList()
    {
        // Arrange
        var expected = "Player added successfully";

        var dbContextMock = new Mock<Context>();
        // Need to setup the Context??

        IRepository gameRepository = new GameRepository(dbContextMock.Object);

        var user = "MyName";

        // Act
        gameRepository.Add(user);

        // Assert

        dbContextMock.VerifySet(o => o.Entry(new ScoreBoard()).State = EntityState.Added);
    }
}

public class ScoreBoard
{

}

Repository

public class GameRepository : IRepository
{
    private readonly Context _context;

    public GameRepository()
        : this(new Context())
    {
        // Blank!
    }

    // Passing in the Mock here...
    public GameRepository(Context context)
    {
        this._context = context;
    }

    // Method under test...
    public void Add<T>(T entity) where T : class
    {
        _context.Set<T>().Add(entity);
    }
}

Context

public class Context : DbContext
{
    public Context()
        : base("name=DefaultConnection")
    {

    }
}
Rovdjuret
  • 1,458
  • 3
  • 19
  • 40
  • Which line throws the exception? Which object is `null`? Where is that object being set? I would *guess* that `.Set()` is returning `null`. The mock probably needs to be told what to return from that during the Arrange step. – David Nov 25 '14 at 15:53
  • _context.Set().Add(entity); <--- This line. And its because the context isn't mocked correctly. Wondering how I should set it up? – Rovdjuret Nov 25 '14 at 15:56
  • 1
    And this is yet another reason that repositories with Entity Framework are an all around bad idea. You're literally testing that the `Add` method of your repo calls the `Add` method of the `DbSet`. That's some ground-breaking stuff there. – Chris Pratt Nov 25 '14 at 16:41
  • @ChrisPratt It's pretty hard for me to figure out. I'm just trying to learn TDD and follow the strict pattern of red, green, refactor... So, basically this is what i have to do if i want this code? Overall, .NET seems to be hard TDD:ing, its a lot of mocking and you seem to have to be an expert :/ Can you point me in an easier direction? – Rovdjuret Nov 25 '14 at 16:43
  • 1
    Well, yeah, sure, but my point is that the act of testing itself should be instructional. When you write a test that's focus is ensuring that you've correctly called `Add` when you want to add something instead of, I don't know, `Delete`, that should tell you that your code is adding complexity, not removing it. – Chris Pratt Nov 25 '14 at 16:46

1 Answers1

1

You need to mock out the Set<T>() call.

Something like this should work out.

// Arrange
var context = new Mock<Context>();
var set = new Mock<DbSet<User>>();

context.Setup(c => c.Set<User>()).Returns(set.Object);

// Act

// Assert
set.Verify(s => s.Add(It.IsAny<User>()), Times.Once());

You don't really need to make verify anything except that Add() was called on the underlying DbSet. Doing your verify on the fact that the Entity state was modified is unnecessary. If you verify that Add() was called that should be enough as you can safely assume that EF is working properly.

This example only works for repositories for your User object. You would have to setup the mocks differently for each repository you want to test in this way. You could probably write up a more generic version of this if needed.

Bradford Dillon
  • 1,750
  • 13
  • 24