【问题标题】:How can we test the stored procedure from the database by using the moq objects in C# Unit Testing?我们如何使用 C# 单元测试中的 moq 对象来测试数据库中的存储过程?
【发布时间】:2019-02-11 17:58:34
【问题描述】:

我在数据库中有两个 sp。我使用 MS 单元测试(实际数据库调用)测试了两个存储过程。在部署中,我遇到了一个问题。我无法访问应用程序服务器中的数据库。这就是我提出最小起订量框架的原因。我需要使用 moq 对象而不是实际的数据库调用来测试这两个存储过程。你能建议我有什么更好的方法吗?除了像 NUnit Test 这样的 MS 单元测试?

我尝试过的:

我已经试过了。只是我创建了一个接口(moq 存储库)并添加了两种方法。

public interface IImintMSNRepository
{  
  bool InsertBulkImportPortfolios(DataTable mSNBulkImportPortfolioTVP,string updatedBy);

    bool InsertBulkImportIndexes(DataTable mSNBulkImportIndexTVP, string updatedBy);
}

我已经通过使用 moq 测试了这两种方法,如下所示。

public readonly IImintMSNRepository MockMSNRepository;

public ImintMSNUnitTests()
{

    Mock<IImintMSNRepository> mockRepo = new Mock<IImintMSNRepository>();
    mockRepo.Setup(a => a.InsertBulkImportPortfolios(It.IsAny<DataTable>(), It.IsAny<string>())).Returns(true);

    mockRepo.Setup(b => b.InsertBulkImportIndexes(It.IsAny<DataTable>(), It.IsAny<string>())).Returns(true);


    this.MockMSNRepository = mockRepo.Object;
}


[TestMethod]
public void TestPortfolioSPByMOQ()
{
    MSNBulkImportPortfolioTVP ptvp = new MSNBulkImportPortfolioTVP();

    DataRow tvprow = ptvp.NewRow();

    tvprow["PortfolioCode"] = "AutomationMoq1";
    tvprow["PortfolioName"] = "AutomationMoqName1";
    tvprow["ClientName"] = "Thomson Reuters";
    tvprow["RIC"] = "IBM.N";
    tvprow["CalculationMethodology"] = "TRGE";
    tvprow["CalendarEventCode"] = "US";
    tvprow["IsProformaPortfolio"] = 1;
    tvprow["IsParentPortfolio"] = 1;
    tvprow["IsGenerateGroupFragment"] = 1;
    tvprow["IsPushLastTick"] = 1;

    ptvp.Rows.Add(tvprow);

    bool expected = true;
    bool actual;

    actual = this.MockMSNRepository.InsertBulkImportPortfolios(ptvp, "MSNMoqUnitTestProcess");
    Assert.AreEqual(expected, actual);
}

谁能帮帮我?

【问题讨论】:

  • 您是否要测试存储过程?或者您是否正在尝试测试调用存储过程的存储库方法?您需要清楚地识别“被测系统”。

标签: c# asp.net sql-server unit-testing moq


【解决方案1】:

考虑在您的工作站上使用 localdb 或 sql server developer 来测试您的工作。然后,使用 tQLt 进行单元测试。

【讨论】:

    【解决方案2】:

    首先你需要回答这个问题

    假设您是从 IImintMSNRepository 继承的实际存储库。这个存储库是如何实例化的?

    假设它是使用连接字符串实例化的

    //this class is assumption cause you need to test an instance of IImintMSNRepository
    public class ImintMSNRepository : IImintMSNRepository
    {
        //assuming you need this if you are doing it using a setting object use that  
        public string ConnectionString {get;set;}
    
        public ImintMSNRepository(string connectionString)
        {
            this.ConnectionString = connectionString;
        }
    
        public bool InsertBulkImportIndexes(DataTable mSNBulkImportIndexTVP, string updatedBy)
        {
            throw new NotImplementedException();
        }
    
        public bool InsertBulkImportPortfolios(DataTable mSNBulkImportPortfolioTVP, string updatedBy)
        {
            throw new NotImplementedException();
        }
    }
    
    public class ImintMSNUnitTests
        {
            public readonly IImintMSNRepository MockMSNRepository; //Don't mock this or create read only, this needs to be tested
    
            public  IImintMSNRepository SUTMSNRepository; //THIS IS SUT SYSTEM UNDER TEST
    
            //you don't need this constructor as well now
            public ImintMSNUnitTests()
            {
    
                Mock<IImintMSNRepository> mockRepo = new Mock<IImintMSNRepository>();
                mockRepo.Setup(a => a.InsertBulkImportPortfolios(It.IsAny<DataTable>(), It.IsAny<string>())).Returns(true);
    
                mockRepo.Setup(b => b.InsertBulkImportIndexes(It.IsAny<DataTable>(), It.IsAny<string>())).Returns(true);
    
    
                this.MockMSNRepository = mockRepo.Object;
            }
    
    
            [Test]
            public void TestPortfolioSPByMOQ()
            {
                //ARRANGE
                MSNBulkImportPortfolioTVP ptvp = new MSNBulkImportPortfolioTVP();
    
                DataRow tvprow = ptvp.NewRow();
    
                tvprow["PortfolioCode"] = "AutomationMoq1";
                tvprow["PortfolioName"] = "AutomationMoqName1";
                tvprow["ClientName"] = "Thomson Reuters";
                tvprow["RIC"] = "IBM.N";
                tvprow["CalculationMethodology"] = "TRGE";
                tvprow["CalendarEventCode"] = "US";
                tvprow["IsProformaPortfolio"] = 1;
                tvprow["IsParentPortfolio"] = 1;
                tvprow["IsGenerateGroupFragment"] = 1;
                tvprow["IsPushLastTick"] = 1;
    
                ptvp.Rows.Add(tvprow);
    
                bool expected = true;
                bool actual;
    
                SUTMSNRepository = new ImintMSNRepository("CONNECTION STRING"); //THIS SHOULD NOT BE A MOCK, THIS SYSTEM UNDER TEST, 
                //MAKE SURE YOU INSTANTIATE THIS AS YOU WANT TO TEST THIS
                //mocking is used mocking the behaviours which is needed to set up the test but not the features you are specifically testing
    
                //ACT
                actual = this.SUTMSNRepository.InsertBulkImportPortfolios(ptvp, "MSNMoqUnitTestProcess");
    
                //ASSERT
                Assert.AreEqual(expected, actual);
    
               //IF ASSERT IS SUCCESSFUL YOU CAN WRITE A CLEANUP METHOD TO REMOVE YOUR UPDATE
            }
        }
    

    不要模拟您的存储库,因为那是您想要测试的。实例化存储库的实际对象并传入连接字符串。一旦你这样做了,你就可以测试断言。

    【讨论】:

      【解决方案3】:

      我可能误解了您想要做什么,但是在数据库不可用时测试存储过程在逻辑上是不可能的。存储过程存在于数据库中,因此您需要访问数据库才能对其进行测试。

      MOQ 用于创建模拟(或假)函数,以替换在单元测试期间不起作用的函数。例如,如果您模拟您的数据库调用,您可以测试调用存储过程而不调用存储过程的更高级别的函数。它会绕过数据库调用并始终返回 true(正如您所做的那样) - 但它实际上并没有测试存储过程。

      如果您想测试存储过程,您实际上是在编写集成测试。我建议将它们放在另一个项目中,并且仅在数据库可用时运行它(然后您可能不需要模拟任何东西)。

      【讨论】:

      • 感谢您的建议。我有一种方法。在那,我通过将参数作为数据表和字符串传递来将数据保存到数据库中来进行数据库调用和存储过程。我想通过使用 moq 对象来测试该方法。你能推荐我吗?
      猜你喜欢
      • 2014-05-02
      • 2020-01-11
      • 2013-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多