如何使用多个存储库进行NUnit测试控制器

时间:2019-11-11 08:47:58

标签: asp.net-core asp.net-web-api nunit-3.0

我有一个带有控制器的.net核心API,该控制器可以处理SQL数据库中的多个表,并且我正在使用存储库模式设计来实现最佳实践。

我的Home控制器的构造函数注入如下所示:

 private IUploadRepository _uploadRepository;
 private ISalesRepository _salesRepository; 
 private ITRSalesRepository _trsalesRepository;
 private ILocalPurchaseRepository _localRepository;

 public HomeController(
      IUploadRepository uploadRepository,
      ISalesRepository salesRepository,
      ITRSalesRepository trsalesRepository,
      ILocalPurchaseRepository localRepository
 )
 {
     this._uploadRepository = uploadRepository;
     this._salesRepository= salesRepository;
     this._trsalesRepository= trsalesRepository;
     this._localRepository= localRepository;
 }

[HttpPost]
public IActionResult PostUpload([FromBody] UploadModel upload)
{
   uploadRepository.Add(upload); // the uploadRepository will save to db
   return Created("Post", upload)
}

我已在StartUp.cs中为这些存储库添加了DI,并且我已验证Home控制器(方法)的行为符合预期。它能够读写SQL数据库。

我的问题是,如何使用NUnit测试来测试此Home控制器的Post操作方法??我有多种利用这些存储库的CRUD方法,因此通常我想对所有单元进行NUnit测试

我尝试对家庭测试类使用构造函数注入,但这不起作用。

谢谢您的帮助!

日期: 我添加了Post方法作为我想在NUnit上进行测试的测试。

2 个答案:

答案 0 :(得分:1)

您可以使用Moq之类的库来创建所需类的模拟

使用最小起订量的粗略示例:

声明您要嘲笑的类:

public Mock<IUploadRepository> UploadService { get; set; } = new Mock<IUploadRepository>();

声明在调用类中的特定方法时应该返回什么。

UploadService.Setup(x => x.ClassMethodIWantToMock("Mock input param"))
                    .Returns(MyMockObject);

实例化HomeController时,您传入创建的Mock类

moq quickstart wiki

答案 1 :(得分:1)

要进行单元测试HomeController,您无需实例化外部依赖项。您可以将它们设为Mock Objects。那里有许多可以为您完成工作的模拟框架。

您的目标是仅对HomeController进行单元测试,并测试与之相关的功能。”使用模拟或存根对象可以最大程度地减少外部依赖项的数量,因此该测试是专注于仅测试一件事。

以下是测试控制器的简单示例。我还创建了一个虚拟项目,您可以在NewEmployeeBuddy.CoreAPI处看到代码:

using Microsoft.AspNetCore.Mvc;
using Moq;
using System.Collections.Generic;
using Xunit;

namespace UnitTestDemo.Tests.Controllers
{
    public class HomeControllerTest
    {
        #region Properties
        protected readonly Mock<IUploadRepository> uploadMockRepository;
        protected readonly Mock<ISalesRepository> salesMockRepository;
        protected readonly Mock<ITRSalesRepository> trsalesMockRepository;
        protected readonly Mock<ILocalPurchaseRepository > localMockRepository;

        protected readonly HomeController controllerUnderTest;
        #endregion

        #region Constructor
        public HomeControllerTest()   
        {   
            //Don't rely on the dependency injection. Define your mock instances for the dependencies.
            uploadMockRepository= new Mock<IUploadRepository>();
            uploadMockRepository.Setup(svc => svc.GetAllEmployees()).Returns();
            salesMockRepository= new Mock<ISalesRepository>();
            trsalesMockRepository= new Mock<ITRSalesRepository>();
            localMockRepository= new Mock<ILocalPurchaseRepository>();

            controllerUnderTest = new HomeController(
            uploadMockRepository.Object,
            salesMockRepository.Object,
            trsalesMockRepository.Object,
            localMockRepository.Object);
        }
        #endregion

        #region Unit Tests
        //Add tests
        #endregion
    }
}