如何使用C#单元测试中的moq对象从数据库中测试存储过程?

问题描述 投票:1回答:3

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

我尝试过的:

我试过这个。我刚创建了一个接口(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
3个回答
0
投票

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


0
投票

首先,你需要回答这个问题

考虑一下从IImintMSNRepository继承的实际Repository。该存储库是如何实例化的?

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

//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
        }
    }

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


0
投票

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

MOQ用于创建模拟(或伪造)函数,以替换在单元测试期间不起作用的函数。例如,如果模拟数据库调用,则可以测试调用存储过程的更高级函数,而无需调用存储过程。它将绕过数据库调用并始终返回true(如您所做) - 但它实际上并未测试存储过程。

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

© www.soinside.com 2019 - 2024. All rights reserved.