将模拟概念应用于现实单元测试时脑冻结

时间:2016-12-01 03:09:56

标签: c# mocking moq

我对与单元测试和模拟有关的概念很新。如果这是一个愚蠢的问题,或者我想出了解这些概念的例子,请原谅我的无知。我们说我有以下界面

public interface IMyService
{
    OrderConfirmation ProcessOrder(Order order);
}

Order和OrderConfirmation类定义如下。

public class Order
{
    public int OrderId { get; set; }
    public int CustomerId { get; set; }
    public List<Product> Products { get; set; }
}

public class Product
{
    public int ProductId { get; set; }
    public string ProductName { get; set; }
    public int Price { get; set; }
}

public class OrderConfirmation
{
    public int OrderConfirmationId { get; set; }
    public int OrderId { get; set; }
    public Shipment ShipmentDetails { get; set; }
}

public class Shipment
{
    public int ShipmentId { get; set; }
    public DateTime ShipmentDate { get; set; }
    public int Cost { get; set; }
}

实现IMyService接口的类的实现如下。这里的关键是它依赖于通过构造函数注入的数据提供者。

public class MyService : IMyService

{
    private IDataProvider DataProvider;

    public MyService(IDataProvider dataProvider)
    {
        DataProvider = dataProvider;
    }

    public OrderConfirmation ProcessOrder(Order request)
    {
        // bunch of operations here including calling various methods of DataProvider to save/retrieve data from databse.

    }
}

IDataProvider接口有许多操作来存储/检索数据库中的数据。

public interface IDataProvider

{
    List<Product> GetAllProducts();
    int CreateOrder(int customerId, List<Product> products);
    int CreateOrderConfirmation(int OrderConfirmationId, int orderId);
    void UpdateListOfAvailableProducts(List<Product> products);

}

为了测试ProcessOrder方法,我似乎不得不以某种方式模拟IDataProvider接口的所有方法,但我真的很困惑如何提供模拟实现(使用)moq。有人可以告诉我如何实现这个目标的任何例子吗?

1 个答案:

答案 0 :(得分:1)

以下是许多假设示例中的一个,如何模拟数据提供程序依赖项。 但是请注意,在没有看到测试方法的真实实现的情况下说些什么是非常模糊的。 HTH

[TestMethod]
public void ProcessOrder_WhenSomeTestedCondition_ThenCertainExpectedResult()
{
    // Arrange
    OrderConfirmation expectedResult = new OrderConfirmation(); // Set expected result here
    Order fakeRequest = new Order();
    List<Product> fakeProducts = new List<Product>();
    int fakeCreateOrderResult = 123;
    int fakeCreateOrderConfirmationResult = 456;

    // This is the mocked dependency
    Mock<IDataProvider> dataProviderMock = new Mock<IDataProvider>();

    // Here the method is setup so it returns some fake products
    dataProviderMock.Setup(dp => dp.GetAllProducts())
        .Returns(fakeProducts);

    // Here the method is setup so it returns some fake result
    dataProviderMock.Setup(dp => dp.CreateOrder(It.IsAny<int>(), It.IsAny<List<Product>>()))
        .Returns(fakeCreateOrderResult);

    // Here the method is setup so it returns some fake result
    dataProviderMock.Setup(dp => dp.CreateOrderConfirmation(It.IsAny<int>(), It.IsAny<int>()))
        .Returns(fakeCreateOrderConfirmationResult);

    // Here the method UpdateListOfAvailableProducts returns void so
    // an example using callback is shouwing how the provided list of new products
    // could update the existing ones
    dataProviderMock.Setup(dp => dp.UpdateListOfAvailableProducts(
        new List<Product> { new Product {Price = 100, ProductId = 1, ProductName = "Product_X"}}))
        .Callback<List<Product>>(np =>
        {
            fakeProducts.AddRange(np);
        });

    // This is class under test which receives the mocked data provider object
    MyService service = new MyService(dataProviderMock.Object);

    // Act
    // Here the tested method is executed
    OrderConfirmation actualResult = service.ProcessOrder(fakeRequest);

    // Assert
    // Compare expected and actual results
    Assert.AreEqual(expectedResult.OrderId, actualResult.OrderId);
}