Asp.net-Mvc

如何將 Moq 與 Entity Framework IDbSet Count() 等方法一起使用

  • April 25, 2013

我正在嘗試Moq對 Entity Framework Code First 類進行一些測試。我對 Moq 和模擬技術非常陌生,我想知道是否可以輕鬆地進行我將在下面描述的測試。我在網上搜尋了一些解決方案,但大多數都是基於儲存庫模式,我想避免這種情況。

我有ITestEntities上下文介面

public interface ITestEntities
{
   IDbSet<Order> Orders { get; }
   IDbSet<Product> Products { get; }
   IDbSet<User> Users { get; }
}

然後上下文

public class TestEntities : DbContext, ITestEntities
{
   public TestEntities() : base("name=TestEntities")
   {

   }

   public virtual IDbSet<Order> Orders { get; set; }
   public virtual IDbSet<Product> Products { get; set; }
   public virtual IDbSet<User> Users { get; set; }
}

一個控制器和一個要測試的動作

public class HomeController : Controller
{
   private ITestEntities db;

   public HomeController()
   {
       db = new TestEntities();
   }

   public HomeController(ITestEntities db)
   {
       this.db = db;
   }

   public ActionResult Index()
   {
       var count = db.Users.Count();
       ViewBag.count = count;

       return View(count);
   }        
}

最後是使用 Moq 的 NUnit 測試

[Test]
public void ModelValueShouldBeTwo()
{
   var mockUsers = new Mock<IDbSet<User>>();
   mockUsers.Setup(m => m.Count()).Returns(2);

   var mockDB = new Mock<ITestEntities>();
   mockDB.Setup(db => db.Users).Returns((IDbSet<User>)mockUsers);

   var controller = new HomeController((ITestEntities)mockDB);

   var view = controller.Index();

   Assert.IsInstanceOf<ViewResult>(view);
   Assert.AreEqual(((ViewResult)view).Model, 2);
}

問題出在這一行:mockUsers.Setup(m => m.Count()).Returns(2);. 執行此測試時,我收到以下錯誤:

System.NotSupportedException : Expression references a method that does not belong to the mocked object: m => m.Count<User>()

我認為這是由於它.Count()是一種靜態方法,因此不能被 Moq 模擬。有沒有一種方法可以使用 Moq 而不是使用成熟的儲存庫模式來測試這個簡單的操作,據我所知,無論如何都應該將這.Count()部分硬編碼為某種可測試的方法……也許我只是以錯誤的方式使用模擬?因為我的印像是使用 EF Code First 應該非常簡單且可行。

如果您正在模擬測試實體,則無需進一步模擬

應該這樣做(雖然,我不在 IDE 中,所以可能需要一些調整)

更新以包含新的 InMemoryDbSet

[Test]
public void ModelValueShouldBeTwo()
{
   //Build test users
   var mockUsers = new InMemoryDbSet<User>(){ new User(), new User()};
   var mockDB = new Mock<ITestEntities>();
   //Set up mock entities to returntest users.
   mockDB.Setup(db => db.Users).Returns(mockUsers);

   var controller = new HomeController((ITestEntities)mockDB);

   var view = controller.Index();

   Assert.IsInstanceOf<ViewResult>(view);
   Assert.AreEqual(((ViewResult)view).Model, 2);
}

這意味著擴展方法將簡單地使用您提供的測試數據。

請參閱下面有關模擬 dbset http://geekswithblogs.net/Aligned/archive/2012/12/12/mocking-or-faking-dbset.aspx的好文章

引用自:https://stackoverflow.com/questions/16210363