[英]How to unit test NpgsqlDataReader extensions in C#
我一直在玩一些受Rob Conery的PostgreSQL Pluralsight文章啟發的ADO.NET擴展。
我是單元測試的新手,並且一直在通過圍繞為NpgsqlDataReader類編寫的幾種擴展方法編寫一些測試來嘗試了解更多有關它的信息。
我嘗試測試的方法的一個示例:
public static T ToEntity<T>(this NpgsqlDataReader reader) where T : new()
{
var result = new T();
var properties = typeof(T).GetProperties();
foreach (var prop in properties)
{
for (var i = 0; i < reader.FieldCount; i++)
{
if (reader.GetName(i).Replace("_", "").Equals(prop.Name, StringComparison.InvariantCultureIgnoreCase))
{
var val = reader.GetValue(i) != DBNull.Value ? reader.GetValue(i) : null;
prop.SetValue(result, val);
}
}
}
return result;
}
我不確定如何開始模擬數據庫連接,因為我要測試的只是迭代返回的結果對象並將列映射到通用實體類的屬性的功能。
我將如何在不訪問數據庫的情況下測試實體映射?
謝謝
更新:
我用來調用上述擴展的代碼是NpgsqlCommand類的另一個擴展:
public static IEnumerable<T> ToList<T>(this NpgsqlCommand cmd) where T : new()
{
var results = new List<T>();
var reader = cmd.ExecuteReader();
while (reader.Read())
{
results.Add(reader.ToEntity<T>());
}
reader.Close();
reader.Dispose();
return results;
}
我還將使用下面答案中發布的相同技術來測試此方法。
首先,該方法的實現不依賴於NpgsqlDataReader的具體實現。 因此,您可以將簽名更改為:
public static T ToEntity<T>(this IDataReader reader) where T : new()
其次,簽名不合邏輯。 數據讀取器用於循環結果集,並產生行列表 (具有0、1或多個元素),而不是單個結果。 因此,更合理的簽名和實現將是:
public static IEnumerable<T> ToEntity<T>(this IDataReader reader) where T : new()
{
var properties = typeof(T).GetProperties();
while (reader.Read())
{
var result = new T();
foreach (var prop in properties)
{
for (var i = 0; i < reader.FieldCount; i++)
{
if (reader.GetName(i).Replace("_", "").Equals(prop.Name, StringComparison.InvariantCultureIgnoreCase))
{
var val = reader.GetValue(i) != DBNull.Value ? reader.GetValue(i) : null;
prop.SetValue(result, val);
}
}
}
yield return result;
}
}
現在,您可以提供IDataReader的虛假實現。 可以使用諸如NSubstitute之類的模擬框架,但是,如果您不熟悉單元測試,則一種更簡單的方法是手動實現。 例如, 在這個要點(不完整的實現)中,我在內存中的通用列表上實現了IDataReader(以及用於方便使用的擴展方法)。
現在您可以編寫這樣的測試方法:
// note the anonymous type here
var expectedEntity = new {MY_PROPERTY = "SomeValue"};
var reader = new[]
{
expectedEntity
}.AsDataReader();
var entity = reader.ToEntity<MyEntity>().First();
Assert.AreEqual("SomeValue", entity.MyProperty);
最終,使用反射的解決方案可行,但最終可能會很慢。 請記住,這種代碼是可以解決的問題。 看看輕量級的ORM,例如PetaPoco,dapper.net ao
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.