私たちの製品の1つに対する単体テストを書いており、Moqを使用してEntity Frameworkへの接続を正常にモックしています。しかし、私は次の方法に出くわしました:
public static productValue findValues(string productName, string dbConnectionString)
{
try
{
SqlConnection conn = new SqlConnection(dbConnectionString);
conn.Open();
//Do stuff
}
}
渡された接続文字列を使用して、そのメソッド内でデータベースにアクセスします。 Moqを使用して模擬DBをセットアップし、模擬DBを指す接続文字列を作成することは可能ですか?私はの線に沿って何かをやってみました
var mockSqlConnnection = new Mock<SqlConnection>();
これが正しいアプローチであるかどうかはわかりませんが、これはDBではなく接続自体をモックするからです。
同様の問題がありました。
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);
}
必要に応じて、ISqlDataContextにオーバーロードを追加できます。
これが意味することは、Moqまたは同様のものを使用する必要に応じてISqlDataContextをモックし、モック値を返すことができるということです。
その後、実際にデータベースにアクセスすることなく、SqlConnectionを介してリポジトリまたはデータベースにアクセスする他の何かをテストできます。
もう1つの利点は、必要に応じてISqlContextにDI/IoCを注入できることです。
遅いが、なぜ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への参照を追加してから、Fakeを追加する必要があります。
https://msdn.Microsoft.com/en-us/library/hh549175.aspx 実装を変更し、使用する読み取り層を変更できる場合は...
Repository Pattern をご覧ください。基本的に、データベースと通信する実装を心配するのではなく、消費するクラスのデータをモックするでしょう。
基本的に、リポジトリがあります
namespace ContosoUniversity.DAL
{
public class StudentRepository : IStudentRepository, IDisposable
{
private SchoolContext context;
public StudentRepository(SchoolContext context)
{
this.context = context;
}
public IEnumerable<Student> 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<IStudentRepository>();
// configure
// act
var controller = new StudentController(mockedRepo.Object);
// do stuff
// assert