3

I'm trying to test my EF repository with MOQ.

My context:

public class PhotoDbContext : DbContext, IDbContext
{
    public PhotoDbContext(){} // to enable data migrations

    public PhotoDbContext(string connectionString, bool debugOutput = false) : base(connectionString)
    {
        if (debugOutput)
            // Write to output all sql operations
            Database.Log = s => Debug.WriteLine(s);
    }

    public virtual new IDbSet<TEntity> Set<TEntity>() where TEntity : class
    {
        return base.Set<TEntity>();
    }

    public virtual new void SaveChanges()
    {
        base.SaveChanges();
    }

    public new DbEntityEntry Entry<TEntity>(TEntity entity) where TEntity : class
    {
        return base.Entry(entity);
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        Configure(modelBuilder);
    }

    public new void Dispose()
    {
        base.Dispose();
    }

    public new DbContextConfiguration Configuration
    {
        get { return base.Configuration; }
    }

My repo:

public  class PhotoRepository : IPhotoRepository
{
    private readonly IDbContext _context;

    public PhotoRepository(IDbContext context)
    {
        _context = context;
    }

    public void Save(Photo album)
    {
        _context.Set<Photo>().Add(album);
        _context.SaveChanges();
    }

    public void Update(Photo entity)
    {
        _context.Set<Photo>().Attach(entity);
        _context.Entry(entity).State = EntityState.Modified; **// null ref exception**
        _context.SaveChanges();
    }

And finally the test im trying to run.

    [TestMethod]
    public void UpdatePhoto()
    {
        var mockSet = new Mock<DbSet<Photo>>();

        var mockContext = new Mock<PhotoDbContext>();
        mockContext.Setup(m => m.Set<Photo>()).Returns(mockSet.Object);

        var service = new PhotoRepository(mockContext.Object);

        var photo = new Photo
        {
            Name = "123",
            Order = 2
        };

        service.Save(photo);

        mockSet.Verify(m => m.Add(It.IsAny<Photo>()), Times.Once);
        mockContext.Verify(m => m.SaveChanges(), Times.Once);

        photo.Name = "updated";
        service.Update(photo);

        mockSet.Verify(m => m.Add(It.IsAny<Photo>()), Times.Exactly(2));
        mockContext.Verify(m => m.SaveChanges(), Times.Exactly(2));
    }

The problem is I am getting a Null reference exception in repositories update method where I try to set Entry.State = Entity.Modified

I tried adding level of indirection in my context but it doesn't work.

What am I missing? Any help would be appreciated.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459

1 Answers1

0

The _context object is your mock object mockContext and the part that is returning null is _context.Entry(entity) because you haven't set this up to return anything within the test.

If you add something like this with the object someObjectThatYouHaveSetup being whatever you want to return from _context.Entry(entity), it should work.

mockContext.Setup(x => x.Entry(photo)).Returns(someObjectThatYouHaveSetup)
TomDoesCode
  • 3,580
  • 2
  • 18
  • 34
  • You can't mock the Entry method because it is not virtual. Need to look a the approach http://stackoverflow.com/questions/5035323/mocking-or-faking-dbentityentry-or-creating-a-new-dbentityentry – bharris9 Jun 10 '16 at 18:17