模拟 DbProviderFactory

发布于 2024-08-05 02:33:34 字数 1278 浏览 10 评论 0原文

我对单元测试相对较新,对模拟也完全陌生。我有一个数据库类,它包装了 DbProvider 工厂,我想在不连接到数据库的情况下为其创建单元测试。

我将如何模拟 DbProvider 工厂,以便我可以将其传递来测试我的类?我还需要模拟 DbConnection、DbCommand 等吗?我的代码的一个小示例如下:

public Database(DbProviderFactory dbProviderFactory) {
    Provider = dbProviderFactory;
}

public int UpdateRecords(string sql, CommandType type, params DbParameter[] parameters) {
    int numberOfRecordsUpdated;

    using (var connection = CreateConnection()) {

        // Add ConnectionString
        connection.ConnectionString = ConnectionString;

        // Create command to hold the update statment
        using (var command = CreateCommand()) {
            try {
                command.Connection = connection;
                command.CommandType = type;
                command.CommandText = sql;

                // Add Parameters
                foreach (var parameter in parameters) {
                    command.Parameters.Add(parameter);
                }

                // Open Connection
                connection.Open();

                // Execute SQL
                numberOfRecordsUpdated = command.ExecuteNonQuery();
            } finally {
                command.Parameters.Clear();
            }
        }
    }

    return numberOfRecordsUpdated;
}

I am relatively new to unit testing, and completely new to mocking. I have a database class that wraps the DbProvider factory that I would like to create unit tests for without connecting to the database.

How would I mock the DbProvider factory, so I could pass it in to test my class? Would I also need to mock the DbConnection, DbCommand, etc.? A small sample of my code follows:

public Database(DbProviderFactory dbProviderFactory) {
    Provider = dbProviderFactory;
}

public int UpdateRecords(string sql, CommandType type, params DbParameter[] parameters) {
    int numberOfRecordsUpdated;

    using (var connection = CreateConnection()) {

        // Add ConnectionString
        connection.ConnectionString = ConnectionString;

        // Create command to hold the update statment
        using (var command = CreateCommand()) {
            try {
                command.Connection = connection;
                command.CommandType = type;
                command.CommandText = sql;

                // Add Parameters
                foreach (var parameter in parameters) {
                    command.Parameters.Add(parameter);
                }

                // Open Connection
                connection.Open();

                // Execute SQL
                numberOfRecordsUpdated = command.ExecuteNonQuery();
            } finally {
                command.Parameters.Clear();
            }
        }
    }

    return numberOfRecordsUpdated;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

随风而去 2024-08-12 02:33:34

集成测试

如果您有兴趣(根据您的评论判断)测试从数据库获取数据,您将执行集成测试

这些类型的测试与单元测试的区别在于它们运行的​​频率较低 - 最佳实践要求您在提交源代码控制之前运行这些测试。

原因是它们速度较慢,并且您将访问真实的数据库(至少是测试数据库)。每次运行时,您都需要擦除数据库或不提交更改 - 您似乎知道自己在做什么,所以我将让您自己决定如何处理此问题。

嘲笑

至于测试使用数据库的逻辑 - 模拟和依赖注入是可行的方法。

我使用 Moq - 它可能是最容易使用的模拟框架。它实际上不仅仅适用于模拟对象(尽管名称如此),您还可以生成存根和假货 有了它。

伪模拟如下(使用数据库示例):

  • 设置模拟
  • 告诉它要做什么(预期) - 例如调用保存。
  • 使用您的 SUT(被测系统)
  • 验证模拟 - 在本例中,保存方法是在您的 SUT 中调用的。

如需进一步帮助 - 检查 Google - 有一些用于单元测试和模拟的好资源。

Integration Testing

If you are interested (as judging by your comment) in testing getting data from the database you will be performing an integration test.

The difference to unit testing for these types of test are they are run less often - best practice dictates you run these before committing to source control.

The reason being they are slower and you will be hitting a real database (a test database at least). On each run you will need to wipe the database or not commit the changes - you seem to know what you're doing here so I'll leave how you handle this up to yourself.

Mocking

As for testing your logic that uses the database - mocking and dependency injection is the way to go.

I use Moq - its probably the easiest mocking framework to use. It actually isn't just for mock objects (despite the name) and you can produce stubs and fakes with it.

Pseudo mocking goes like this (using a DB example):

  • Set up mock
  • Tell it what to do (expect) - e.g. a call to save.
  • Use your SUT (System Under Test)
  • Verify the mock - in this case that the save method was called within your SUT.

For further help - check Google - there are some good resources out there for unit testing and mocking.

慕烟庭风 2024-08-12 02:33:34

我个人会模拟包含更高级别数据访问功能(如 UpdateRecords 等)的类,并使用此模拟返回预定的数据集。

DbProvider 和相应的 DbCommand 等的使用是数据访问层的实现细节,与使用返回值的更高级别功能并不真正相关。

I would personally mock the class that contains the higher level data access functionality (like UpdateRecords etc) and use this mock to return the predetermined datasets.

The use of DbProvider and the corresponding DbCommand etc are an implementation detail of your data access layer and not really relevant to the higher level functionality that uses the returned values.

烟织青萝梦 2024-08-12 02:33:34

数据访问类都是关于与数据库集成的。例如,Roy Osherove 在单元测试时认为此类是一个例外。我也对如何测试此类代码感兴趣。问题+1。

IOW 我不确定是否建议模拟数据访问类。

单元测试时不应该测试什么?< /a>

Data access classes are all about integrating with DB. Roy Osherove for example consider this classes an exception when unit testing. I'm interested too on how to test this type of code. +1 for question.

IOW I'm not sure that it's advisable to mock around data access classes.

What not to test when it comes to Unit Testing?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文