Moq和SqlConnection?

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

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

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

 var mockSqlConnnection = new Mock(); 

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

我有类似的问题。

我在SqlConnection周围引入了一个SqlDataContext包装器,它inheritance自和ISqlDataContext接口:

 class SqlDataContext : ISqlDataContext { private readonly SqlConnection _connection; public SqlDataContext(string connectionString) { _connection = CreateConnection(connectionString); } public IDataReader ExecuteReader(string storedProcedureName, ICollection 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 parameters); } 

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

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

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

另一个优点是您可以根据需要向DI / IoC注入ISqlContext。

看一下Repository Pattern ,基本上你会模拟你的消费类中的数据,而不是担心与数据库交谈的实现。


从本质上讲,您将拥有一个存储库

 namespace ContosoUniversity.DAL { public class StudentRepository : IStudentRepository, IDisposable { private SchoolContext context; public StudentRepository(SchoolContext context) { this.context = context; } public IEnumerable GetStudents() { return context.Students.ToList(); } // ... more 

然后在其他类中使用它:

  public class StudentController : Controller { private IStudentRepository studentRepository; public StudentController(IStudentRepository studentRepository) { this.studentRepository = studentRepository; } 

用作:

  public ViewResult Index(string sortOrder, string currentFilter, string searchString, int? page) { var students = from s in studentRepository.GetStudents() select s; 

完整示例位于顶部的链接中。


那么你就可以将一个模拟的存储库传递给你的类:

 // arrange var mockedRepo = new Mock(); // configure // act var controller = new StudentController(mockedRepo.Object); // do stuff // assert 

迟到但为什么不用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"); } } 

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

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