Moq和SqlConnection?

Nov*_*orm 14 c# database unit-testing moq

我正在为我们的某个产品编写单元测试,并使用Moq成功模拟与Entity Framework的连接.但是,我遇到了以下方法:

public static productValue findValues(string productName, string dbConnectionString)
{
    try
    {
        SqlConnection conn = new SqlConnection(dbConnectionString);
        conn.Open();
        //Do stuff 
    }
}
Run Code Online (Sandbox Code Playgroud)

它使用传递的连接字符串访问该方法内的数据库.是否可以使用Moq设置模拟数据库并创建指向模拟数据库的连接字符串?我正在尝试做一些事情

var mockSqlConnnection = new Mock<SqlConnection>();
Run Code Online (Sandbox Code Playgroud)

虽然我不确定这是否是正确的方法,因为这会模拟连接本身而不是数据库.

Gra*_*ham 10

我遇到了类似的问题.

我介绍了一个SqlDataContext围绕SqlConnection 的包装器,它继承自和ISqlDataContext接口:

class SqlDataContext : ISqlDataContext {

    private readonly SqlConnection _connection;

    public SqlDataContext(string connectionString)
    {
        _connection = CreateConnection(connectionString);
    }

    public IDataReader ExecuteReader(string storedProcedureName, ICollection<SqlParameter> parameters)
    {
       // execute the command here using the _connection private field.
       // This is where your conn.Open() and "do stuff" happens.
    }

    private SqlConnection CreateConnection(string connectionString)
    {
        if (string.IsNullOrEmpty(connectionString))
        {
            throw new ArgumentNullException("connectionString");
        }

        return new SqlConnection(connectionString);
    }
}

interface ISqlDataContext
{
    IDataReader ExecuteReader(string storedProcedureName, ICollection<SqlParameter> parameters);
}
Run Code Online (Sandbox Code Playgroud)

您可以根据需要向ISqlDataContext添加重载.

这意味着您可以根据需要使用Moq或类似方法模拟ISqlDataContext并返回模拟值.

这意味着您可以测试您的存储库或通过SqlConnection访问数据库的任何其他内容,而无需实际访问数据库.

另一个优点是您可以根据需要使用DI/IoC注入ISqlContext.

  • 虽然这个实现可以让你模拟IDataReader的创建,但你现在有一个漏洞的实现,会导致错误消息"无法从池中获取连接"(http://stackoverflow.com/questions/ 15848239 /如何对解决-MAX连接池错误).这是因为您没有"处置"您的SqlConnection(或SqlCommand).我建议也实现IDisposable接口(https://msdn.microsoft.com/en-us/library/system.idisposable(v=vs.110).aspx)并在你的使用周围加上一个"using"语句这个SqlDataContext对象. (9认同)

tir*_*011 6

迟到但为什么不用mstest:

[TestMethod]
MyTestWithInternSqlConnection()
{
   using (ShimsContext.Create())
   {
      // simulate a connection
      ShimSqlConnection.AllInstances.Open = connection => { };
      string commandText;

      // shim-Mock all called methods
      ShimSqlCommand.AllInstances.ExecuteReader = command =>
      {
         commandText = command.CommandText;
         return new ShimSqlDataReader();
      };

      int readCount = 0;
      ShimSqlDataReader.AllInstances.Read = reader => readCount == 0;
      ShimSqlDataReader.AllInstances.GetSqlStringInt32 = (reader, i) =>
      {
         readCount++;
         return "testServer";
      };

      var theReadedString = AMethodUnderTestThatReadsFromDatabaseAString();
      Assert.IsTrue(theReadedString == "testServer");
   }
}
Run Code Online (Sandbox Code Playgroud)

你需要添加对System.Data的引用,然后为它添加一个假.

https://msdn.microsoft.com/en-us/library/hh549175.aspx 更好的是,如果你改变实现,你可以改变使用过的读取层但是......