2012-04-04 85 views
0

我想從我的控制器測試刪除方法。單元測試刪除控制器方法

我有以下的測試案例:

[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)); 

    } 

這是控制器方法

[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); 
     } 

    } 

然而,當我運行測試情況下,我得到下面的異常。

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

我通過調試運行測試,發現以下行的問題:

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

我不知道爲什麼會這樣。

+0

單元測試應該模擬數據庫上下文,並設置在執行期間在該上下文上執行的每個方法的期望您可以設置預定義的返回數據。模擬你的上下文,設置Entry和SaveChanges的期望值。你目前正在做的是編寫一個集成測試,它測試的不僅僅是控制器方法,還測試了數據庫上下文的集成。 – Nope 2012-04-04 13:10:51

回答

2

我在這裏看到的最大問題是您正在直接針對數據庫進行測試。你的單元測試應該嘲笑數據庫依賴關係。

但是,如果你這樣做是死的,那麼你得到的錯誤來自於你的測試打開了CoursesDBContext,然後你的代碼似乎在使用它自己的CoursesDBContext。所以,錯誤是因爲你不能嘗試從不同的上下文中引用同一個實體。您需要一些方法將您的上下文傳遞給您的類(公共屬性或通過參數傳遞)

+0

謝謝。我將銘記未來。 – keshav 2012-04-04 16:08:29