How to fake SqlDataAdapter, SqlConnection and SqlCommand in unit tests

I'm trying to figure out how I can run unit tests in a class that I created to execute queries in a database, but I keep running around in circles trying to figure out how to fake all the dependencies. My class implements IDisposable, which closes the SqlConnection if it is open. A typical method (I have a bit overloaded) for selecting data is as follows:

public DataSet SelectData(string selectCommand)
    {
        if (!string.IsNullOrEmpty(selectCommand))
        {
            DataSet ds = new DataSet();
            ds.Locale = CultureInfo.InvariantCulture;
            SqlDataAdapter adapter = new SqlDataAdapter(selectCommand, Connection);
            adapter.Fill(ds);
            return ds;
        }
        throw new ArgumentException("SelectCommand was null or empty", "selectCommand");
    }

Note that the Connection parameter in the SqlCommand constructor is a property that returns the SqlConnection for this instance of my class. Obviously, I need to fake the SqlDataAdapter somehow, but it also means that I have to fake the SqlCommand and SqlConnection. All classes are sealed, so I canโ€™t just create a fake object that inherits from these classes. Creating a database type defeats the goal of dependency injection, so I would like to avoid this. Does anyone have a suggestion on how to test this method?

+3
source share
2 answers

, (1) , , (2) () / . TypeMock , . , , ( , , - ). , , . - , .

, , - (ORM). Entity, LINQ-to-SQL, nHibernate, Subsonic... - , , .

+7

, (IDbConnection, IDbTransaction, IDbCommand IDbDataAdapter), , , NSubstitute Injection Dependency.

//using init class to inject IDbDataAdapter
IDbDataAdapter adapter = init.DbAdapter("command");
adapter.Connection = connection;

SqlConnection SqlCommand

using (IDbConnection connection = init.DbConnection("connection"))
{
  using (IDbTransaction transaction = connection.BeginTransaction())
  {
    using (IDbCommand command = init.DbCommand("sproc"))
    {  
       command.Transaction = transaction;
       command.Connection = connection;
       ...
    }
  }
}

Unit test :

//arrange
var connection = Substitute.For<IDbConnection>();
var command = Substitute.For<IDbCommand>();
var transaction = Substitute.For<IDbTransaction>();
//this is the init class used before
var init = Substitute.For<ISqlInitializer>();
connection.Open();
connection.BeginTransaction(Arg.Any<IsolationLevel>()).Returns(transaction);
init.DbConnection(Arg.Any<string>()).Returns(connection);
init.DbCommand(Arg.Any<string>()).Returns(command);
var client = new SqlClient(init);

//act
var result = await client.CommandMultipleAsync(new SqlConfiguration(FakeConnection, new List<string> { "testSproc1", "testSproc2" }));

//assert
Assert.AreEqual(0, result);
command.Received(2).ExecuteNonQuery();
transaction.Received(1).Commit();

, GitHub , : p https://github.com/TianyuanC/dals/blob/master/DALs.Sql/SqlClient.cs

+3

All Articles