单元测试难题:OleDbCommand



我尝试单元测试的类之一使用了OleDbConnection对象。此对象负责根据传递的 SQL 字符串返回 MS Access 文件中保存的信息。代码为:

public void getInformation(DateTime start, DateTime finish)
{
    string getInfo = "";
    string query = "//Query for MS Access goes here";
    transactions = addTransactions(query, conn);
}

其中 addTransactions 是一个私有方法,它返回从数据库中检索到的列表:

private List<string> addTransactions(string query, OleDbConnection conn)
{
    List<string> returnedData = new List<string>();
    OleDbCommand cmd = new OleDbCommand(query, conn);
    try
    {
        if (conn.State == ConnectionState.Closed) conn.Open();
        OleDbDataReader reader = cmd.ExecuteReader();
        while (reader.Read())
        {
            if (!reader.IsDBNull(0))
        }
        returnedData.Add(reader.GetString(0));
    }
    catch (Exception ex)
    {
        Console.WriteLine("OLEB: {0}", ex.Message);
    }
    conn.Close();
    return returnedData;
}

现在我已经从查看此方法中知道单元测试将很困难,因为公共 getInformation() 方法是无效的。我能做的是测试返回的数据中是否有内容。我的问题是我如何编写涉及 OleDbConnection 的单元测试?

我想到的唯一 2 个潜在解决方案涉及创建一个临时访问文件(不理想,因为我们现在超出了单元测试的范围,再加上在其他开发人员的机器上运行测试时可能会失败)或为 OleDbConnection 创建一个包装器并在单元测试中使用它(这听起来像是最好的方法, 但我不知道从哪里开始)。

或为 OleDbConnection 创建一个包装器并在单元测试中使用它

这就是我的做法。 不能直接模拟/测试的对象通常表示其本身的依赖关系。 并且应该提供所有依赖项,而不是内部实例化。

包装器可以是提供相同功能的简单直通。 让它由接口和该接口的代码驱动,以便您可以为该接口提供模拟以进行单元测试。 (作为额外的奖励,即使正在测试的方法返回void,您的模拟也会让您观察一些东西。 因此,您不必太深入地钻研正在测试的系统,只需观察模拟中调用的内容即可。

从你模拟的内容的聚合根开始,你需要包装OleDbConnection。 一个简单的入门示例可能如下所示:

public interface IDbConnection
{
    IDbCommand CreateCommand();
    // other methods
}
public class MyOleDbConnection : IDbConnection
{
    private OleDbConnection conn;
    public MyOleDbConnection()
    {
        // initialize "conn" here
    }
    public IDbCommand CreateCommand()
    {
        return conn.CreateCommand();
    }
    // other pass-thru methods
}

从本质上讲,它只是一个传递包装器,用于底层对象公开的相同功能。 这样做的好处是这个对象实际上不需要进行单元测试,因为它不包含任何有意义的可测试逻辑。 (当然,达到 100% 会很好,但这个级别的投资回报率并不存在。

如您所见,这也涉及以类似的方式为OleDbCommand创建包装器。 同样,只是直通方法。

一旦你的依赖项被包装和可模拟,你就可以更改你的类来使用包装器。 例如,代替这个:

OleDbCommand cmd = new OleDbCommand(query, conn);

它在内部包含对依赖项的引用,您将执行以下操作:

IDbCommand cmd = conn.CreateCommand();

它要求依赖项引用某物。 这将维护依赖项的责任放在依赖项本身上,而不是在你尝试测试的这个类中。 (并且,在这样做时,试图保持对依赖项的自由。

从类中完全删除依赖项后,您可以自由地模拟和测试您喜欢的所有内容。

只需创建一个 MS 文件并放入包中,然后始终使用相同的文件进行测试,这样您甚至可以写入数据并确切地知道它返回的内容,而不是假设如果返回任何数据是正确的!只是一个想法,有多种方法可以做到。

相关内容

  • 没有找到相关文章

最新更新