Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add an item to a Mock DbSet (using Moq)

Tags:

c#

linq

moq

dbset

I'm trying to set up a mock DbSet for testing purposes. I used the tutorial here, http://www.loganfranken.com/blog/517/mocking-dbset-queries-in-ef6/ and slightly modified it so calling GetEnumerator returns a new enumerator each time (another problem i was having). However, I am having difficulty adding items to the DbSet.

The output is preCount = 3 postCount = 3. However, I expect it to be precount = 3 postCount = 4. Any help is greatly appreciated.

static void Main(string[] args)     {         Debug.WriteLine("hello debug");          List<string> stringList = new List<string>         {             "a", "b", "c"         };          DbSet<string> myDbSet = GetQueryableMockDbSet(stringList);         int preCount = myDbSet.Count();         myDbSet.Add("d");         int postCount = myDbSet.Count();         Debug.WriteLine("preCount = " + preCount + " postCount = " + postCount);     }      private static DbSet<T> GetQueryableMockDbSet<T>(List<T> sourceList) where T : class     {         var queryable = sourceList.AsQueryable();          var dbSet = new Mock<DbSet<T>>();         dbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(queryable.Provider);         dbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(queryable.Expression);         dbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(queryable.ElementType);         dbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(() => queryable.GetEnumerator());          return dbSet.Object;     } 
like image 748
user1080952 Avatar asked Jul 10 '15 20:07

user1080952


People also ask

What can be mocked with MOQ?

Unit testing is a powerful way to ensure that your code works as intended. It's a great way to combat the common “works on my machine” problem. Using Moq, you can mock out dependencies and make sure that you are testing the code in isolation.

How does MOQ mock work?

Mock objects allow you to mimic the behavior of classes and interfaces, letting the code in the test interact with them as if they were real. This isolates the code you're testing, ensuring that it works on its own and that no other code will make the tests fail.


1 Answers

myDbSet is not real implementation of DbSet but a mock which means it's fake and it needs to be setup for all methods you need. The Add is not exception so it needs to be set up to do what you need otherwise it does nothing.

Add something like the following and when the myDbSet.Add("d"); is called then the 'd' is added to the list and can be returned later.

dbSet.Setup(d => d.Add(It.IsAny<T>())).Callback<T>((s) => sourceList.Add(s)); 

Complete code

private static DbSet<T> GetQueryableMockDbSet<T>(List<T> sourceList) where T : class {     var queryable = sourceList.AsQueryable();      var dbSet = new Mock<DbSet<T>>();     dbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(queryable.Provider);     dbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(queryable.Expression);     dbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(queryable.ElementType);     dbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(() => queryable.GetEnumerator());     dbSet.Setup(d => d.Add(It.IsAny<T>())).Callback<T>((s) => sourceList.Add(s));      return dbSet.Object; } 

Output

hello debug preCount = 3 postCount = 4 
like image 83
Daniel Dušek Avatar answered Oct 02 '22 10:10

Daniel Dušek