如何使用Moq测试与数据库交互的方法?

时间:2013-12-02 11:05:07

标签: c# unit-testing asp.net-mvc-4 moq

在我的MVC4应用程序中,几乎每个方法都使用数据库。现在我想测试这些方法,然后我查看了this教程。建议在那里使用Moq来制作模拟对象。

在这种特殊情况下,我想测试GetTotal类的ShoppingCart方法(基于Microsoft Tutorial),该方法取决于AddToCart方法,如下所示< / p>

public class ShoppingCart() {
    projectContext db = new projectContext ();

    public virtual void AddToCart(Product product)
    {
        var cartItem = db.Carts.SingleOrDefault(
            c => c.CartId == ShoppingCartId
            && c.ProductId == product.ProductId);

        if (cartItem == null)
        {  
            cartItem = new Cart
            {
                ProductId = product.ProductId,
                CartId = ShoppingCartId,
                Count = 1,
                DateCreated = DateTime.Now
            };
            db.Carts.Add(cartItem);
        }
        else
        {
            cartItem.Count++;
        }
        db.SaveChanges();
    }

    public virtual decimal GetTotal()
    {  
        decimal? total = (from cartItems in db.Carts
                          where cartItems.CartId == ShoppingCartId
                          select (int?)cartItems.Count *
                          cartItems.Product.Price).Sum();

        return total ?? decimal.Zero;
    }
}

可以看出,两种方法都依赖于projectContext实例db。

在测试这些方法时,我想使用这样的模拟对象:

[TestClass]
public class ShoppingCartTest : DbContext
{

    [TestMethod]
    public void GetTotalTest()
    {
        // Arrange
        var _cart = new Mock<ShoppingCart>() { CallBase = true };
        var _mock = new Mock<Product>() { CallBase = true };
        _mock.SetupGet(m => m.Price).Returns(10.00M);

        // Act
        _cart.AddToCart() // cannot find method since no definiton can be found

        // Assert
       Assert.AreEqual(10.00M, _cart.GetTotal());// cannot find GetTotal method since no definiton can be found
    }

}

我怎样才能可能测试这些方法?是否可以创建一个“假的”数据库并使用它?或者我可以调整模拟对象的方式可以使用方法(在我看来,使用“模拟方法”就像错过了测试实际方法的点......)

2 个答案:

答案 0 :(得分:1)

测试这很难,我不确定是否可以嘲笑这个。如果您可以使用DI(依赖注入),您可以解决所有问题。通过使用DI,您可以模拟projectContext类并使其返回您需要的任何内容。查看Autofac(http://www.codeproject.com/Articles/25380/Dependency-Injection-with-Autofac),它可能已经安装在您的mvc解决方案中。

答案 1 :(得分:1)

您的问题是您的ShoppingCart类与数据库层直接耦合。

隐藏对抽象背后的具体projectContext的依赖,例如接口,因此您可以在测试使用它的生产代码时替换它。

取决于抽象......