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



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

我尝试过的:

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

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

我已经通过使用如下所示的最小起订量测试了这两种方法。

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);
}

有人可以帮我吗?

考虑在工作站上使用 localdb 或 sql Server 开发人员来测试您的工作。 然后,使用 tQLt 进行单元测试。

首先你需要回答这个问题

考虑从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
}
}

不要嘲笑你的仓库,因为这是你想要测试的。实例化存储库的实际对象并传入连接字符串。完成此操作后,您可以测试断言。

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

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

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

最新更新