Why is the DBSet Add failing, and also destroying the existing Customer entries in the DBSet?

418 views Asked by At

Our programming involves some Mock testing using In Memory Data.

      // Let us create some in-memory data
        // Create a list of Customer
        List<Customer> listOfCustomers =  new List<BlahProjectBlahExample.Domain.Objects.Customer>()
                                   { new Customer { CustomerID = "1    ", CompanyName = "Chicago Bulls", ContactName = "Michael Jordan", ContactTitle = "top basket ball player", Address = "332 testing lane", City = "Chicago", Region = "Illinois", PostalCode = "484894", Country = "USA", Phone = "3293993", Fax = "39393" },
                                     new Customer { CustomerID = "2    ", CompanyName = "Miami Heat", ContactName = "Lebron James", ContactTitle = "second best basket ball player", Address = "90 test street", City = "Miami", Region = "Florida", PostalCode = "4869394", Country = "USA", Phone = "3293213", Fax = "33393" },
                                     new Customer { CustomerID = "3    ", CompanyName = "Oklahoma City Thunder", ContactName = "Kevin Durant", ContactTitle = "current top basket ball player", Address = "35 test row", City = "Oklahoma City", Region = "Oklahoma", PostalCode = "480290", Country = "USA", Phone = "304923", Fax = "33325" }
                                   };
        // Convert the list to an IQueryable list
        IQueryable<Customer> queryableListOfCustomerInMemoryData = listOfCustomers.AsQueryable();


        // Let us create a Mocked DbSet object.
        Mock<DbSet<BlahProjectBlahExample.Domain.Objects.Customer>> mockDbSet = new Mock<DbSet<BlahProjectBlahExample.Domain.Objects.Customer>>();

     // Force DbSet to return the IQueryable members
        // of our converted list object as its 
        // data source
        mockDbSet.As<IQueryable<BlahProjectBlahExample.Domain.Objects.Customer>>().Setup(m => m.Provider).Returns(queryableListOfCustomerInMemoryData.Provider);
        mockDbSet.As<IQueryable<BlahProjectBlahExample.Domain.Objects.Customer>>().Setup(m => m.Expression).Returns(queryableListOfCustomerInMemoryData.Expression);
        mockDbSet.As<IQueryable<BlahProjectBlahExample.Domain.Objects.Customer>>().Setup(m => m.ElementType).Returns(queryableListOfCustomerInMemoryData.ElementType);
        mockDbSet.As<IQueryable<BlahProjectBlahExample.Domain.Objects.Customer>>().Setup(m => m.GetEnumerator()).Returns(queryableListOfCustomerInMemoryData.GetEnumerator());



         Mock<BlahProjectBlahDataContext> mockedReptryCtxt = new Mock<BlahProjectBlahDataContext>();


         mockedReptryCtxt.Setup(q => q.Customers).Returns(mockDbSet.Object);
         mockedReptryCtxt.Setup(q => q.Set<Customer>()).Returns(mockDbSet.Object);
        mockedReptryCtxt.CallBase = true;




        DbSet<Customer> inMemoryDbSetCustomer = mockedReptryCtxt.Object.Set<Customer>();

In the following code, I used a loop to see the contents of the inMemoryDbSetCustomer, and it contained the expected data.

      Customer something;
      foreach (var entry in inMemoryDbSetCustomer)
      {
          something = entry as Customer;
      }

Sadly, when I try to add a new customer, 1) the inMemoryDbSetCustomer fails to add the customer 2) the inMemoryDbSetCustomer.Add(someCust) returns NULL 3) the inMemoryDbSetCustomer seems to have lost all it's other Customer entries.

        Customer someCust = new Customer { CustomerID = "4    ", CompanyName = "Kolkota Knights", ContactName = "Sachin Tendulkar", ContactTitle = "current top cricket player", Address = "35 test row", City = "Kolkota", Region = "West Bengal", PostalCode = "3454534", Country = "India", Phone = "304923", Fax = "33325" };
        try
        {
            Customer returnCust = (Customer)(inMemoryDbSetCustomer.Add(someCust));
        }
        catch(Exception ex ){

        }

Why is the DBSet Add failing, and also destroying the existing Customer entries in the DBSet?

Update With Answer

Thanks to @Werlang suggestion. The following code addition helped:

 mockDbSet.Setup(m => m.Add(It.IsAny<Customer>()))
                   .Callback<Customer>((Customer c) => { listOfCustomers.Add(c); })
                   .Returns((Customer c) => c);

Also, if you mocking DBSets with Moq Framework like I am then the following stackoverflow posting will be helpful because you might face a similar problem:

What steps to get rid of Collection was modified; enumeration operation may not execute. Error?

1

There are 1 answers

0
André Werlang On BEST ANSWER

You've mocked the queryable to return a fixed set of data, when accessed via IQueryable. But Add's are maintained in a separated list on DbContext internal in the form of DbEntry's.

I suggest you to mock the Add() method too, addind the new element to mocked array (listOfCustomers).