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更好的是,如果你改变实现,你可以改变使用过的读取层但是…