Search code examples
c#asp.net-mvcentity-frameworkmstestdbcontext

My DbSet<Entity> won't update when trying from Unit Testing (MSTest) code


I am unit testing my MVC application. One of the tests is validating if my controller is correctly returning data for provided id.

To Unit test it, I want to add data from my [TestMethod] to the Context.DBSet and then call my Controller method and validate its output.

However, my added record isn't reflected inside the Context.DBSet object.

Below is the code that I currently have.

    ///for purpose of unit testing, there is no underlying database
    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        public ApplicationDbContext()
        {
            Database.SetInitializer(new ApplicationDbContextInitializer());
        }

        public static ApplicationDbContext Create()
        {
            return new ApplicationDbContext();
        }
        public DbSet<Book> Books { get; set; }
        public DbSet<Customer> Customers { get; set; }
    }
    public class ApplicationDbContextInitializer : CreateDatabaseIfNotExists<ApplicationDbContext>
    {
        protected override void Seed(ApplicationDbContext context)
        {
            InitializeBooks(context);
            InitializeCustomers(context);
            base.Seed(context);
        }
    }
    //for brevity, i haven't posted the InitializeBooks & InitializeCustomers()
    //these methods create Book and Customer objects
    //and do context.Book.Add(objBook) and context.Customer.Add(objCustomer)

My Controller class has DbContext object which I use in my MS Test

    public class CustomersController : Controller
    {
        public ApplicationDbContext db = new ApplicationDbContext();

        ///other methods exist too
    }

Finally my MSTest

[TestMethod]
public void TestCustomerIDReplacedCorrectly()
{
    var objCtrl = new CustomersController();
    Customer objCust = new Customer()
    {
        Name = "Foo Bar",
        Address = "Hello World",
    };

    Console.WriteLine(objCtrl.db.Customers.Count()) //returns 4 correctly
    objCtrl.db.Customers.Add(objCust);
    Console.WriteLine(objCtrl.db.Customers.Count()) //still returns 4!? it should return 5

    ///calls are given to controller method
    ///to fetch ViewResult and ViewBag
    ///to validate if it is processing the
    ///instance put inside the objCtrl.db.Customers
}

I see that the added customer is not reflected inside by Customer's DbContext object, thus even my actual controller method which I'm supposed to validate, doesn't reflect my desired behavior either. How do I ensure that my objCust is added to objCtrl.db.Customers.Add

Here is the InitializeCustomers() code which is called for seeding

        private void InitializeCustomers(ApplicationDbContext context)
        {
            Customer cust1 = new Customer()
            {
                Name = "James Butt",
                Address = "6649 N Blue Gum St",
                Contact = "50-621 8927",
                NationalID = "12312312312"
            };

            Customer cust2 = new Customer()
            {
                Name = "Josephine Darakjy",
                Address = "Chanay, Jeffrey A Esq",
                Contact = "81-292 9840",
                NationalID = "123123124"
            };

            Customer cust3 = new Customer()
            {
                Name = "Art Venere",
                Address = "Chemel, James L Cpa",
                Contact = "85-636 8749",
                NationalID = "123123456"
            };


            Customer cust4 = new Customer()
            {
                Name = "Lenna Paprocki",
                Address = "Feltz Printing Service",
                Contact = "90-385 4412",
                NationalID = "32165498712"
            };

            context.Customers.Add(cust1);
            context.Customers.Add(cust2);
            context.Customers.Add(cust3);
            context.Customers.Add(cust4);

        }

Solution

  • You need to call objCtrl.db.SaveChanges(); for the object to be added to the DbSet. Currently, you aren't doing so and objCtrl.db.Customers.Count() queries the database for the count of objects currently stored in the database. Since you haven't called SaveChanges yet, you're object has not been written to the database and will not be included in the .Count() method call.

    It's common to use a separate db which is only used for testing and seeded with the needed data (if any is needed) to test. Often, you'll see each test wrapped in a transaction so that you can perform the needed test, validate data, then rollback all of the operations so the database is back at it's starting state for each test