unit testing a Delete controller method

Go To StackoverFlow.com

0

I am trying to test the delete method from my controller.

I have the following test case:

    [TestMethod()]
    [DeploymentItem("Courses.sdf")]
    public void RemoveCourseConfirmedTest()
    {

        CoursesController target = new CoursesController();
        int id = 50;

        ActionResult actual;
        CoursesDBContext db = new CoursesDBContext();
        Course courseToDelete = db.Courses.Find(id);
        List<CourseMeet> meets = db.Meets.Where(a => a.courseID == id).ToList();
        actual = target.RemoveCourseConfirmed(courseToDelete);
        foreach (CourseMeet meet in meets)
        {
            Assert.IsFalse(db.Meets.Contains(meet));
        }
        Assert.IsFalse(db.Courses.Contains(courseToDelete));

    }

This is the controller method

    [HttpPost, ActionName("RemoveCourse")]
    public ActionResult RemoveCourseConfirmed(Course course)
    {
        try
        {
            db.Entry(course).State = EntityState.Deleted;
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        catch (DbUpdateConcurrencyException)
        {
            return RedirectToAction("RemoveMeet", new System.Web.Routing.RouteValueDictionary { { "concurrencyError", true } });
        }
        catch (DataException)
        {
            ModelState.AddModelError(string.Empty, "Unable to save changes. Try again.");
            return View(course);
        }

    }

However when I run the test case I get the following exception.

System.InvalidOperationException: An entity object cannot be referenced by multiple instances of IEntityChangeTracker.

I ran the test through the debugger and found that the problem in on the following line:

db.Entry(course).State = EntityState.Deleted;

I am not sure why this is happening.

2012-04-04 00:33
by keshav
A unit test should mock the DB Context and set expectation for each method executed on that context during the execution for which you set predefined return data. Mock your Context, set expectations for Entry and SaveChanges. What you are currently doing is writing an integration test which tests more than the controller method but also tests the integration of the DB Context - Nope 2012-04-04 13:10


2

The biggest problem I see here is that you are testing directly against the database. Your unit tests should mock out the database dependencies especially.

However, if you are deadset on doing it this way, then the error you are getting is coming from the fact that your test is opening a CoursesDBContext, and then your code under test appears to be using its own CoursesDBContext. So, the error is because you cannot try to reference the same entity from different contexts. You will need some way of passing in your context to your class (either a public property or being passed through the parameters)

2012-04-04 04:51
by Justin Pihony
Thank you. I will keep it in mind for the future - keshav 2012-04-04 16:08