共用方式為


單元測試與泛型

更新:2007 年 11 月

HOW TO:產生單元測試所述,您可以產生泛型方法的單元測試,而且產生的方式與其他方法的單元測試完全相同。下列章節提供建立泛型方法之單元測試的相關資訊與範例。

型別引數和型別條件約束

在產生泛型類別 (例如 MyList<T>) 的單元測試時,Visual Studio 會產生兩個方法:一個泛型 Helper 方法和一個測試方法。如果 MyList<T> 具有一個或多個型別條件約束 (Constraint),則型別引數必須滿足所有的型別條件約束。為了確定受測試的泛型程式碼是否如預期般適用於允許的所有輸入,測試方法會使用您想測試的所有條件約束來呼叫泛型 Helper 方法。

範例

下列範例說明泛型的單元測試:

  • 編輯產生的測試程式碼.本範例包含「產生的測試程式碼」和「編輯的測試程式碼」兩個區段。其示範如何將由泛型方法產生之未經處理的測試程式碼,編輯成有用的測試方法。

  • 使用型別約束條件.本範例示範的單元測試適用於使用型別條件約束的泛型方法。本範例中並未滿足型別條件約束。

範例 1:編輯產生的測試程式碼

此區段中的測試程式碼測試的是名稱為 SizeOfLinkedList() 的受測試程式碼方法。這個方法會傳回指定連結串列 (Linked List) 中節點數目的整數。

「產生的測試程式碼」區段中的第一個程式碼範例顯示 Visual Studio Team System Test 版所產生的原始測試程式碼。「編輯的測試程式碼」區段中的第二個程式碼範例,則顯示如何針對 int 和 char 兩種不同的資料型別來測試 SizeOfLinkedList 方法的運作狀況。

此程式碼說明兩個方法:

  • 測試 Helper 方法,SizeOfLinkedListTestHelper<T>()。根據預設,測試 Helper 方法的名稱中包含 "TestHelper" 字串。

  • 測試方法,SizeOfLinkedListTest()。每個測試方法都會以 TestMethod 屬性 (Attribute) 標示。

產生的測試程式碼

下列測試程式碼是從 SizeOfLinkedList() 方法產生。因為這項產生的測試尚未經過編輯,所以您必須修改它才能正確測試 SizeOfLinkedList 方法。

public void SizeOfLinkedListTestHelper<T>()

{

    T val = default(T); // TODO: Initialize to an appropriate value

    MyLinkedList<T> target = new MyLinkedList<T>(val); // TODO: Initialize to an appropriate value

    int expected = 0; // TODO: Initialize to an appropriate value

    int actual;

    actual = target.SizeOfLinkedList();

    Assert.AreEqual(expected, actual);

    Assert.Inconclusive("Verify the correctness of this test method.");

}

[TestMethod()]

public void SizeOfLinkedListTest()

{

   SizeOfLinkedListTestHelper<GenericParameterHelper>();

}

在前面的程式碼中,泛型型別參數是 GenericParameterHelper。雖然您可以編輯此參數來提供特定的資料型別 (如下面的範例所示),但是您也可以直接執行測試,不對這個陳述式進行任何編輯。

編輯的測試程式碼

在下列程式碼中,測試方法和測試 Helper 方法都已經過編輯,使其能夠成功測試受測試程式碼方法 SizeOfLinkedList()。

測試 Helper 方法

測試 Helper 方法會執行下列步驟,而這些步驟與程式碼中標記為步驟 1 到步驟 5 的各行相對應。

  1. 建立泛型連結串列。

  2. 將四個節點附加到連結串列。這些節點中有資料型別未知的內容。

  3. 將預期的連結串列大小指派給變數 expected。 

  4. 計算連結串列的實際大小,並將它指派給變數 actual。

  5. 比較 Assert 陳述式中的 actual 與 expected。如果 actual 不等於 expected,測試便會失敗。

測試方法

測試方法會編譯到您在執行名為 SizeOfLinkedListTest 之測試時所呼叫的程式碼中。它會執行下列步驟,而這些步驟與程式碼中標記為步驟 6 和步驟 7 的各行相對應。

  1. 在呼叫測試 Helper 方法時指定 <int>,以驗證此測試是否適用於 integer 變數。

  2. 在呼叫測試 Helper 方法時指定 <char>,以驗證此測試是否適用於 char 變數。 

public void SizeOfLinkedListTestHelper<T>()
{
    T val = default(T); 
    MyLinkedList<T> target = new MyLinkedList<T>(val); // step 1
    for (int i = 0; i < 4; i++) // step 2
    {
        MyLinkedList<T> newNode = new MyLinkedList<T>(val);
        target.Append(newNode);
    }
    int expected = 5; // step 3
    int actual;
    actual = target.SizeOfLinkedList(); // step 4
    Assert.AreEqual(expected, actual); // step 5
}

[TestMethod()]
public void SizeOfLinkedListTest() 
{
    SizeOfLinkedListTestHelper<int>();  // step 6
    SizeOfLinkedListTestHelper<char>(); // step 7
}
注意事項:

每次 SizeOfLinkedListTest 測試執行時,都會呼叫其 TestHelper 方法兩次。Assert 陳述式每次都必須判定為 true,測試才會通過。如果測試失敗,可能無法確定造成失敗的是指定 <int> 的呼叫,還是指定 <char> 的呼叫。如果要找出答案,您可以檢查呼叫堆疊,也可以在測試方法中設定中斷點,然後在執行測試時同時進行偵錯。如需詳細資訊,請參閱 HOW TO:在 ASP.NET 方案中執行測試時偵錯

範例 2:使用型別條件約束

本範例示範泛型方法的單元測試,而該泛型方法使用了未能滿足的型別條件約束。第一個區段顯示來自受測試程式碼專案的程式碼。其中的型別條件約束以反白顯示。

第二個區段顯示來自測試專案的程式碼。

受測試程式碼專案

using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;

namespace ClassLibrary2
{
    public class Employee
    {
        public Employee(string s, int i)
        {
        }
    }

    public class GenericList<T> where T : Employee
    {
        private class Node
        {
            private T data;
            public T Data
            {
                get { return data; }
                set { data = value; }
            }
        }
    }
}

測試專案

如同所有新產生的單元測試一樣,您必須將非結果不明的 Assert 陳述式加入至此單元測試,使它傳回有用的結果。您不會將它們加入至標記為 TestMethod 屬性的方法,而會加入至 "TestHelper" 方法 (在此測試中的名稱為 DataTestHelper<T>())。

在這個範例中,泛型型別參數 T 具有條件約束 where T : Employee。測試方法並未滿足此條件約束。因此,DataTest() 方法包含 Assert 陳述式,以提醒您必須提供對 T 所設的型別條件約束。此 Assert 陳述式的內容如下:("No appropriate type parameter is found to satisfies the type constraint(s) of T. " + "Please call DataTestHelper<T>() with appropriate type parameters.");

換句話說,當您從測試方法呼叫 DataTestHelper<T>() 方法 DataTest() 時,您必須傳遞型別為 Employee 的參數,或衍生自 Employee 的類別 (Class)。

using ClassLibrary2;

using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace TestProject1

{
    [TestClass()]
    public class GenericList_NodeTest
    {
    
        public void DataTestHelper<T>()
            where T : Employee
        {
            GenericList_Shadow<T>.Node target = new GenericList_Shadow<T>.Node(); // TODO: Initialize to an appropriate value
            T expected = default(T); // TODO: Initialize to an appropriate value
            T actual;
            target.Data = expected;
            actual = target.Data;
            Assert.AreEqual(expected, actual);
            Assert.Inconclusive("Verify the correctness of this test method.");
        }

        [TestMethod()]
        public void DataTest()
        {
            Assert.Inconclusive("No appropriate type parameter is found to satisfies the type constraint(s) of T. " +
            "Please call DataTestHelper<T>() with appropriate type parameters.");
        }
    }
}

請參閱

其他資源

單元測試概觀

建立單元測試