1

I am developing an Asp.Net mvc application. I am doing unit testing to my application. I use Moq to mock objects. In my test I need to mock database context and its DbSets. I can mock database context and test. But the problem is I have to change from DbSet<Entity> Entities to IDbSet<Entity> Entities in context class.

This is example of how I mock context class

[TestMethod]
    public void GenerateItemCode_IncreaseDigit()
    {
        var data = new List<Item>{
            new Item{
                Id = 2,
                ItemCode = "CD345678"
            }
        }.AsQueryable();
        var dbSetMock = new Mock<IDbSet<Item>>();
        dbSetMock.Setup(m => m.Provider).Returns(data.Provider);
        dbSetMock.Setup(m => m.Expression).Returns(data.Expression);
        dbSetMock.Setup(m => m.ElementType).Returns(data.ElementType);
        dbSetMock.Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());

        var storeContext = new Mock<StoreContext>();
        storeContext.Setup(x => x.Items).Returns(dbSetMock.Object);

        ItemRepo itemRepo = new ItemRepo(storeContext.Object);
        string itemCode = itemRepo.GenerateItemCode();
        Assert.AreEqual(itemCode, "CD345679");
    }

This is context class

 public class StoreContext : DbContext, IDisposable
    {
        public StoreContext():base("DefaultConnection")
        {

        }

         public virtual IDbSet<Item> Items { get; set; }
 protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {

        }
    }

When I use IDbSet instead of DbSet, my application goes down in performance. Because I cannot use as below

context.Items.Include("Promotions")//Cannot use Include with IDbSet
context.Items.AddRange(items)//cannot use AddRange with IDbSet
context.Items.RemoveRange(items)//cannot with IDbSet

So I changed from IDbSet to DbSet in context class as below

public virtual DbSet<Item> Items { get; set; }

Then unit tests start throwing errors. Because items of context class cannot be mocked with the way I am mocking. Below is the screenshot of errors.

enter image description here

So I changed from IDbSet to DbSet in Unit Test. Then the errors become like this.

enter image description here

How can I mock DbSet entities of context class for unit tests?

2
  • you have just forget to change in your test method the IDbSet to DbSet: var dbSetMock = new Mock<DbSet<Item>>(); this will solve your problem. shall I post this comment as answer? Commented Jul 10, 2016 at 18:58
  • I changed it to DbSet. Cannot solve the issue. I updated the question Please see it. Please how can I solve that? Commented Jul 10, 2016 at 19:27

1 Answer 1

1

After the question update I can reproduce your problem. You have just forget to cast to the correct interface IQueryable:

  var dbSetMock = new Mock<DbSet<Item>>();
      dbSetMock.As<IQueryable<Item>>().Setup(m => m.Provider).Returns(data.Provider);
      dbSetMock.As<IQueryable<Item>>().Setup(m => m.Expression).Returns(data.Expression);
      dbSetMock.As<IQueryable<Item>>().Setup(m => m.ElementType).Returns(data.ElementType);
      dbSetMock.As<IQueryable<Item>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());

If you want to know why you must cast to make it possible to setting the provider that because the explicit interface implementation of the IQueryable. More info : https://msdn.microsoft.com/en-us/library/aa288461(v=vs.71).aspx

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.