如何在单元测试中使用moq对象?

Paw*_*wan 2 unit-testing dependency-injection moq asp.net-mvc-4

我正在对我的一个进行单元测试Service layer class(ProductService).该层为其中一个提供DI工具controller class(ProductController).对于ProductController单元测试,已经有一个单元测试类ProductControllerTest.

但是对于单元测试ProductController的服务层(ProductService),我创建了一个新的单元测试类(ProductServiceTest).

但我不知道我是否应该创建一个新的单元测试类来进行服务层单元测试.

另外我想知道DI(Dependency Injection) and Mocking(MOQ object)单元测试的概念.在单元测试中何时使用MOQ以及何时需要使用?

我已经为ProductService的一个动作方法编写了单元测试代码.我想知道它是否正确?

以下是Action Method的代码: -

public class ProductService : IProductService
{
    private readonly IProductDal<Product> _productDal;
    private readonly IUserDal<Users> _userDal;

    public ProductService(IProductDal<Product> ProductDAL)
    {
        _productDal = ProductDAL;
    }


    public List<ProductDto> GetProducts(string SearchInName, string SearchInDescription)
    {
          List<ProductDto> productList = new List<ProductDto>();
          foreach (Product product in _productDal.GetProducts(SearchInName, SearchInDescription))
          {
               productList.Add(Adapter.AdaptOmToDto(product));
          }
          return productList;
    }
}
Run Code Online (Sandbox Code Playgroud)

下面是单元测试(ProductServiceTest)类的代码片段: -

    [TestMethod]
    public void GetProductsTest()
    {
        var productList = new List<ProductDto>();

        // Arrrange            
        var Name = "CreateSave";
        var Description = "CreateSave";

        // Act
        List<ProductDto> output = _productService.GetProducts(Name, Description);

        // Assert       
        Assert.IsNotNull(output);
        Assert.IsInstanceOfType(output, typeof(List<ProductDto>));
    }
Run Code Online (Sandbox Code Playgroud)

任何人都可以建议我对这种方法进行单元测试的最佳方法吗?

Ser*_*kiy 6

另外,我想知道单元测试中DI(依赖注入)和Mocking(MOQ对象)的概念

依赖注入是我们使应用程序遵循依赖性反转原则的方式,该原则指出高级模块不应该依赖于低级模块 - 两者都应该依赖于抽象.根据抽象,您可以在系统中实现单元的低耦合,并能够将依赖类的任何抽象依赖实现.这里有与单元测试相关的部分 - 你可以给出依赖的模拟实现,这将允许你验证被测单元的行为(参见Mocks Are Not Stubs文章).

您已经通过ProductService依赖抽象来做得很好,并且您使用DI将抽象实现注入服务.测试服务行为所需要的是注入ProductService模拟的抽象实现,并设置和模拟之间的预期交互:

ProductService _productService;
Mock<IProductDal<Product>> _productDalMock;

[TestInitialize]
public void Setup()
{
    // create mock of dependency and pass mocked object to service
    _productDalMock = new Mock<IProductDal<Product>>();
    _productService = new ProductService(productDalMock.Object);
}

[TestMethod]
public void ShouldNotReturnDtosWhenProductsNotFound()
{
    // Arrrange 
    var name = "CreateSave";
    var description = "CreateSave";
    // setup mocked dal to return empty list of products
    // when name and description passed to GetProducts method
    _productDalMock.Setup(d => d.GetProducts(name, description))
                   .Returns(new List<Product>());

    // Act
    List<ProductDto> actual = _productService.GetProducts(name, description);

    // Assert
    Assert.False(actual.Any());
    // verify all setups of mocked dal were called by service
    _productDalMock.VerifyAll();
}
Run Code Online (Sandbox Code Playgroud)

正如您在上面的测试中所看到的,您可以检查产品服务是否使用正确的参数调用其依赖关系,并且您可以设置依赖关系返回服务的数据.对于下一个测试,您可以设置mock以返回预定义产品的列表.然后,您将验证服务是否返回了适当的dtos.