測試泛型方法需驗證多種型別引數,手寫重複測試碼違反 DRY 原則。VS2012 提供 Microsoft.VisualStudio.TestTools.UnitTesting.GenericParameterHelper 作為預設型別引數,但型別約束泛型 (如 where T : struct) 需自訂測試協助類。
public static bool IsCollectionEmpty<T>(ICollection<T> collection)
{
return collection == null || collection.Count < 1;
}
public void IsCollectionEmptyTestHelper<T>()
{
// Case 1: 非空集合
ICollection<T> collection = new T[] { default(T) };
Assert.IsFalse(UtilityCheckData.IsCollectionEmpty<T>(collection));
// Case 2: 空集合
collection = new T[] { };
Assert.IsTrue(UtilityCheckData.IsCollectionEmpty<T>(collection));
// Case 3: null
Assert.IsTrue(UtilityCheckData.IsCollectionEmpty<T>(null));
}
[TestMethod]
public void IsCollectionEmptyTest()
{
// 使用框架提供的 GenericParameterHelper 作為型別引數
IsCollectionEmptyTestHelper<GenericParameterHelper>();
}
public class StackNum<T> where T : struct
{
List<T> _array = new List<T>();
public void Push(T value) { _array.Add(value); }
public T Pop() { var v = _array[_array.Count - 1]; _array.RemoveAt(_array.Count - 1); return v; }
public int Length { get { return _array.Count; } }
}
static class StackTestHelper
{
public static void LengthTest<T>() where T : struct
{
var stack = new StackNum<T>();
Assert.AreEqual(0, stack.Length);
}
public static void PushTest<T>() where T : struct
{
var stack = new StackNum<T>();
stack.Push(default(T));
Assert.AreEqual(1, stack.Length);
}
public static void PopTest<T>(params T[] values) where T : struct
{
var stack = new StackNum<T>();
if (values == null) return;
foreach (var v in values) { stack.Push(v); Assert.AreEqual(stack.Length, Array.IndexOf(values, v) + 1); }
for (int i = values.Length - 1; i >= 0; i--)
{
Assert.AreEqual(values[i], stack.Pop());
Assert.AreEqual(i, stack.Length);
}
}
}
[TestClass]
public class StackTest
{
[TestMethod] public void PushTest() { StackTestHelper.PushTest<decimal>(); StackTestHelper.PushTest<double>(); }
[TestMethod] public void PopTest() { StackTestHelper.PopTest<int>(22, 33, 55); StackTestHelper.PopTest<bool>(true, false); }
[TestMethod] public void LengthTest() { StackTestHelper.LengthTest<char>(); }
}
DataSource 屬性從 XML/CSV 讀取型別清單,動態建構測試。MethodInfo.MakeGenericMethod 於運行時組合測試案例。where T : class, new() 等複合約束時,協助類需對應約束聲明。泛型單元測試關鍵在於「抽象測試邏輯 → 具象化型別引數」。無約束泛型用 GenericParameterHelper;有約束泛型自訂協助類並明確聲明 where 子句。良好的測試結構讓泛型程式碼品質可控、可維護。