gpt4 book ai didi

c# 单元测试,模拟存储过程

转载 作者:太空狗 更新时间:2023-10-29 20:33:08 25 4
gpt4 key购买 nike

在过去,当我一直在实现单元测试时,我一直在努力为数据访问层设置“体面”的单元测试,因为它们通常将数据库作为外部依赖项。在理想的世界中,我会模拟存储过程调用,以便删除外部依赖性。

但是我一直无法弄清楚如何使用最小起订量模拟框架来执行此操作,也无法找到支持此功能的任何其他框架。相反,我已经恢复到创建一个包含已知数据的脚本测试数据库(这样我总能得到我期望的输出),但这与模拟该层略有不同。

谁能建议如何模拟数据访问层的这一部分[我知道 Entity Framework https://effort.codeplex.com/存在]?


详情例如,如果我有以下方法

public object RunStoredProc()
{
//Some Setup

using (SqlConnection conn = new SqlConnection(CONNNECTION_STRING))
{
using (SqlCommand comm = new SqlCommand("storedProcName", conn))
{
conn.Open();
comm.CommandType = CommandType.StoredProcedure;
using (SqlDataReader reader = comm.ExecuteReader())
{
while (reader.Read())
{
//Logic
}
}
}
}

//Return object based on logic
}

然后如何模拟存储过程输出,以便 SQLDataReader 包含指定的数据。在更高层次上,我可以模拟 RunStoredProc() 方法 - 但这无助于我测试该方法中的逻辑是否正确。或者我可以将 SQLReader 剥离到另一个方法中

public object RunStoredProc()
{
//Some Setup

List<object> data = GetData();
//Logic

//Return object based on logic
}

private List<object> GetData()
{
using (SqlConnection conn = new SqlConnection(CONNNECTION_STRING))
{
using (SqlCommand comm = new SqlCommand("storedProcName", conn))
{
conn.Open();
comm.CommandType = CommandType.StoredProcedure;
using (SqlDataReader reader = comm.ExecuteReader())
{
while (reader.Read())
{
//place into return object
}
}
}
}
}

但由于“GetData”方法应该是私有(private)的(不是已发布接口(interface)的一部分),我将无法模拟它,所以问题仍然存在。

最佳答案

我认为我们拥有所有接口(interface)(IDbConnectionIDbTransactionIDbCommandIDataReader)并借用了一个来自 EF (IDbConnectionFactory) 的想法是抽象所有需要的东西,以便它们可以被模拟并与依赖注入(inject)一起使用。我认为 SqlConnection 和其他更多的是实现细节,可以抽象出来。

按照 Entity Framework 的想法,您可以创建一个连接工厂

public interface IDbConnectionFactory {
/// <summary>
/// Creates a connection based on the given database name or connection string.
IDbConnection CreateConnection(string nameOrConnectionString);
}

然后您可以重构您的示例方法以仅使用抽象。

public class MyDataAccessClass {
private IDbConnectionFactory dbConnectionFactory;
private string CONNNECTION_STRING = "Connection string here";

public MyDataAccessClass(IDbConnectionFactory dbConnectionFactory) {
this.dbConnectionFactory = dbConnectionFactory;
}

public object RunStoredProc() {
//Some Setup
List<object> result = new List<object>();

using (IDbConnection conn = dbConnectionFactory.CreateConnection(CONNNECTION_STRING)) {
using (IDbCommand comm = conn.CreateCommand()) {
comm.CommandText = "storedProcName";
conn.Open();
comm.CommandType = CommandType.StoredProcedure;
using (IDataReader reader = comm.ExecuteReader()) {
while (reader.Read()) {
//...Logic to populate result
}
}
}
}

//Return object based on logic
return result;
}
}

从那里您可以使用您选择的模拟框架模拟接口(interface),或者创建您自己的伪造来注入(inject)和测试您的方法。

[TestClass]
public class StoredProcedureUnitTest {
[TestMethod]
public void TestRunStoredProc() {
//Arrange
var connectionFactory = new Mock<IDbConnectionFactory>();
//..Setup...

var sut = new MyDataAccessClass(connectionFactory.Object);

//Act
var actual = sut.RunStoredProc();

//Assert
//...
}
}

关于c# 单元测试,模拟存储过程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38954886/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com