在 c# 中使用 Moq 进行模拟

时间:2023-02-26
本文介绍了在 c# 中使用 Moq 进行模拟的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

我有以下代码:

public interface IProductDataAccess
{
    bool CreateProduct(Product newProduct);
}

ProductDataAccess 实现该接口.

public class ProductBusiness
{
    public bool CreateProduct(Product newProduct)
    {
        IProductDataAccess pda = new ProductDataAccess();
        bool result = pda.CreateProduct(newProduct);
        return result;
    }
}

在这种情况下,如何通过模拟 IProductDataAccess 接口为 CreateProduct 方法创建单元测试?我想在 ProductBusiness 中有一个 IProductDataAccess 的公共实例并使用 Mock 对象对其进行初始化,但公开它不是一个好习惯对 UI 层的数据访问.谁能帮帮我?

In this case, how to create unit test for CreateProduct method by mocking the IProductDataAccess interface? I thought of having an public instance of IProductDataAccess within ProductBusiness and initialize it using Mock<IProductDataAccess> object but it is not a good practice to expose the data access to the UI layer. Can any one help me?

推荐答案

经典示例演示如果您无法对特定组件进行单元测试,请对其进行重构!

Classic example which demonstrates that if you cannot unit test a particular component, REFACTOR it!

这就是为什么我喜欢任何模拟框架强制您执行的操作 - 编写解耦代码.

This is why I love what any mocking framework enforces you to do - write decoupled code.

在您的示例中,ProductBusiness 类与 ProductDataAccess 类紧密耦合.您可以使用(就像大多数答案建议的那样)依赖注入来解耦它.通过这样做,您最终将依赖于 IProductDataAccess 抽象,而不是依赖于它的任何具体实现.

In your example, the ProductBusiness class is tightly coupled with the ProductDataAccess class. You could decouple it using (like most of the answers suggest) dependency injection. By doing so, you would end up depending on the IProductDataAccess abstraction and not on any concrete implementation of it.

还有一点需要注意,当您为业务层编写测试/规范时,您通常希望测试行为"而不是状态".因此,尽管您可以断言验证是否返回true",但您的测试应该真正测试使用 MOQ 设置的预期数据访问调用是否实际使用 MOQ 的 .Verify API 执行.

Another point to note, when you are writing tests/specifications for the business layer, you would typically want to test the "behavior" and not the "state". So, although you could have asserts that verify if "true" was returned, your tests should really test if the expected data access calls that were set using MOQ were actually executed using the .Verify API of MOQ.

尝试在您希望数据访问层抛出异常(使用.Throws"API)的地方添加行为测试,并检查您是否需要在业务层进行任何特殊处理.

Try adding behavior tests where you expect an exception to be thrown (using the ".Throws" API) by the data access layer and check if you need any special handling at the business layer.

就像 Kevin 建议的那样,ProductBusiness 的以下实现将起作用:

Like Kevin suggests, the following implementation of ProductBusiness will work:

public class ProductBusiness
{
  private readonly IProductDataAccess  _productDataAccess;

  public ProductBusiness(IProductDataAccess productDataAccess)
  {
      _productDataAccess = productDataAccess;
  }

  public bool CreateProduct(Product newProduct)
  {
    bool result=_productDataAccess.CreateProduct(newProduct);
    return result;
  }
}

并使用任何 xunit 测试框架将测试编写为:

and use any xunit testing framework to write the test as:

 var mockDataAccess = new Mock<IProductDataAccess>();
 mockDataAccess.Setup(m => m.CreateProduct(It.IsAny<Product>())).Returns(true);
 var productBusiness = new ProductBusiness(mockDataAccess.Object);
 //behavior to be tested

这篇关于在 c# 中使用 Moq 进行模拟的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

上一篇:MSBuild 找不到参考 下一篇:每个主要的模拟框架在现实世界中的优缺点是什么?

相关文章

最新文章