如何模拟sqlconnection还是应该重构代码? [英] how do I mock sqlconnection or should I refactor the code?

查看:67
本文介绍了如何模拟sqlconnection还是应该重构代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有下面的代码,我已阅读 Moq和SqlConnection?

I have the code below, I have read Moq and SqlConnection? and How can I stub IDBconnection, but I still have no idea how to mock the following sqlconnection.

public class SqlBulkWriter : ISqlBulkWriter
{
    private readonly string _dbConnectionString;;

    public SqlBulkWriter(string dbConnectionString)
    {
        this._dbConnectionString = dbConnectionString;
    }

    public void EmptyTable(string schema, string tableName)
    {
        using (var connection = new SqlConnection(this._dbConnectionString))
        {
            try
            {
                connection.Open();
                using (var truncate = new SqlCommand($"TRUNCATE TABLE [{schema}].[{tableName}] ", connection))
                {
                    truncate.ExecuteNonQuery();
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex);
            }
            finally
            {
                connection.Close();
            }
        }
    }
}

我将为EmptyTable做单元测试,我想我应该首先模拟sqlconnection?或如何对EmptyTempTable进行单元测试?

I'm going to do the unit test for EmptyTable, I think I should mock the sqlconnection firstly? or how do I do the unit test for the EmptyTempTable?

谢谢!许多人感激!

推荐答案

SqlBulkWriter类与实现方面的关注紧密相关,这使得很难单独测试该类.

SqlBulkWriter class is tightly coupled to implementation concerns which make it difficult to test the class in isolation.

知道连接字符串并不是该类真正关心的问题,可以将其委托给另一个服务.

Knowing the connection string is not really a concern of that class and can be delegated out to another service.

类似

public interface IDbConnectionFactory {
   IDbConnection CreateConnection();
}

及其在您的类中的实现如下所示

and its implementation for your class would look something like this

public class SqlConnectionFactory : IDbConnectionFactory {
    private readonly string dbConnectionString;

    public SqlConnectionFactory(string dbConnectionString) {
        this.dbConnectionString = dbConnectionString;
    }

    public IDbConnection CreateConnection() {
        return new SqlConnection(this.dbConnectionString);
    }
}

现在可以将

SqlBulkWriter类重构为依赖于抽象而不是依赖.

SqlBulkWriter class can now be refactored to depend on the abstraction instead of the concretion.

public class SqlBulkWriter : ISqlBulkWriter {
    private readonly IDbConnectionFactory connectionFactory;

    public SqlBulkWriter(IDbConnectionFactory connectionFactory) {
        this.connectionFactory = connectionFactory;
    }

    public void EmptyTable(string schema, string tableName) {
        using (var connection = connectionFactory.CreateConnection()) {
            try {
                connection.Open();
                using (var command = connection.CreateCommand()) {
                    command.CommandText = $"TRUNCATE TABLE [{schema}].[{tableName}] ";
                    command.CommandType = CommandType.Text;
                    int rowsAffected = command.ExecuteNonQuery();
                }
            } catch (Exception ex) {
                throw ex;
            } finally {
                connection.Close();
            }
        }
    }
}

这可以简化类的测试,因为可以对那些抽象进行模拟并将其注入到类中.

This allows the class to easier to be tested in isolation as those abstractions can be mocked and injected into the class.

[TestClass]
public class SqlBulkWriter_Should {
    [TestMethod]
    public void EmptyTable() {
        //Arrange
        var mock = new MockRepository(MockBehavior.Default);
        var command = mock.OneOf<IDbCommand>();
        var connection = mock.OneOf<IDbConnection>(_ => _.CreateCommand() == command);
        var factory = mock.OneOf<IDbConnectionFactory>(_ => _.CreateConnection() == connection);

        var subject = new SqlBulkWriter(factory);
        var schema = "dbo";
        var tableName = "TestTable";

        //Act
        subject.EmptyTable(schema, tableName);

        //Assert
        Mock.Get(command).Verify(_ => _.ExecuteNonQuery(), Times.Once());
    }
}

参考 Moq快速入门,以更好地了解如何使用该框架.

Reference Moq Quickstart to get a better understanding of how to use the framework.

这篇关于如何模拟sqlconnection还是应该重构代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆