title | description | ms.date | ms.topic | helpviewer_keywords | ms.author | manager | ms.subservice | author | ||
---|---|---|---|---|---|---|---|---|---|---|
Unit tests for Generic Methods | Learn how to generate unit tests for generic methods by using this information about and examples of creating unit tests for generic methods. | 11/04/2016 | conceptual |
| mikejo | mijacobs | test-tools | mikejo5000 |
You can generate unit tests for generic methods exactly as you do for other methods. The following sections provide information about and examples of creating unit tests for generic methods.
When Visual Studio generates a unit test for a generic class, such as MyList<T>
, it generates two methods: a generic helper and a test method. If MyList<T>
has one or more type constraints, the type argument must satisfy all the type constraints. To make sure that the generic code under test works as expected for all permissible inputs, the test method calls the generic helper method with all the constraints that you want to test.
The following examples illustrate unit tests for generics:
Edit generated test code. This example has two sections, Generated Test Code and Edited Test Code. It shows how to edit the raw test code that is generated from a generic method into a useful test method.
Use a type constraint. This example shows a unit test for a generic method that uses a type constraint. In this example, the type constraint is not satisfied.
The test code in this section tests a code-under-test method named SizeOfLinkedList()
. This method returns an integer that specifies the number of nodes in the linked list.
The first code sample, in the section Generated Test Code, shows the unedited test code as it was generated by Visual Studio Enterprise. The second sample, in the section Edited Test Code, shows how you could make it test the functioning of the SizeOfLinkedList method for two different data types, int
and char
.
This code illustrates two methods:
a test helper method,
SizeOfLinkedListTestHelper<T>()
. By default, a test helper method has "TestHelper" in its name.a test method,
SizeOfLinkedListTest()
. Every test method is marked with the TestMethod attribute.
The following test code was generated from the SizeOfLinkedList()
method. Because this is the unedited generated test, it must be modified to correctly test the SizeOfLinkedList method.
publicvoidSizeOfLinkedListTestHelper<T>(){Tval=default(T);// TODO: Initialize to an appropriate valueMyLinkedList<T>target=newMyLinkedList<T>(val);// TODO: Initialize to an appropriate valueintexpected=0;// TODO: Initialize to an appropriate valueintactual;actual=target.SizeOfLinkedList();Assert.AreEqual(expected,actual);Assert.Inconclusive("Verify the correctness of this test method.");}[TestMethod()]publicvoidSizeOfLinkedListTest(){SizeOfLinkedListTestHelper<GenericParameterHelper>();}
In the preceding code, the generic type parameter is GenericParameterHelper
. Whereas you can edit it to supply specific data types, as shown in the following example, you could run the test without editing this statement.
In the following code, the test method and the test helper method have been edited to make them successfully test the code-under-test method SizeOfLinkedList()
.
The test helper method performs the following steps, which correspond to lines in the code labeled step 1 through step 5.
Create a generic linked list.
Append four nodes to the linked list. The data type of the contents of these nodes is unknown.
Assign the expected size of the linked list to the variable
expected
.Compute the actual size of the linked list and assign it to the variable
actual
.Compare
actual
withexpected
in an Assert statement. If the actual is not equal to the expected, the test fails.
The test method is compiled into the code that is called when you run the test named SizeOfLinkedListTest. It performs the following steps, which correspond to lines in the code labeled step 6 and step 7.
Specify
<int>
when you call the test helper method, to verify that the test works forinteger
variables.Specify
<char>
when you call the test helper method, to verify that the test works forchar
variables.
publicvoidSizeOfLinkedListTestHelper<T>(){Tval=default(T);MyLinkedList<T>target=newMyLinkedList<T>(val);// step 1for(inti=0;i<4;i++)// step 2{MyLinkedList<T>newNode=newMyLinkedList<T>(val);target.Append(newNode);}intexpected=5;// step 3intactual;actual=target.SizeOfLinkedList();// step 4Assert.AreEqual(expected,actual);// step 5}[TestMethod()]publicvoidSizeOfLinkedListTest(){SizeOfLinkedListTestHelper<int>(); // step 6SizeOfLinkedListTestHelper<char>();// step 7}
Note
Each time the SizeOfLinkedListTest test runs, its TestHelper method is called two times. The assert statement must evaluate to true every time for the test to pass. If the test fails, it might not be clear whether the call that specified <int>
or the call that specified <char>
caused it to fail. To find the answer, you could examine the call stack, or you could set breakpoints in your test method and then debug while running the test. For more information, see How to: Debug while running a test in an ASP.NET solution.
This example shows a unit test for a generic method that uses a type constraint that is not satisfied. The first section shows code from the code-under-test project. The type constraint is highlighted.
The second section shows code from the test project.
usingSystem;usingSystem.Linq;usingSystem.Collections.Generic;usingSystem.Text;namespaceClassLibrary2{publicclassEmployee{publicEmployee(strings,inti){}}publicclassGenericList<T>whereT:Employee{privateclassNode{privateTdata;publicTData{get{returndata;}set{data=value;}}}}}
As with all newly generated unit tests, you must add non-inconclusive Assert statements to this unit test to make it return useful results. You do not add them to the method marked with the TestMethod attribute but to the "TestHelper" method, which for this test is named DataTestHelper<T>()
.
In this example, the generic type parameter T
has the constraint where T : Employee
. This constraint is not satisfied in the test method. Therefore, the DataTest()
method contains an Assert statement that alerts you to the requirement to supply the type constraint that has been placed on T
. The message of this Assert statement reads as follows: ("No appropriate type parameter is found to satisfies the type constraint(s) of T. " + "Please call DataTestHelper<T>() with appropriate type parameters.");
In other words, when you call the DataTestHelper<T>()
method from the test method, DataTest()
, you must pass a parameter of type Employee
or a class derived from Employee
.
usingClassLibrary2;usingMicrosoft.VisualStudio.TestTools.UnitTesting;namespaceTestProject1{[TestClass()]publicclassGenericList_NodeTest{publicvoidDataTestHelper<T>()whereT:Employee{GenericList_Shadow<T>.Nodetarget=newGenericList_Shadow<T>.Node();// TODO: Initialize to an appropriate valueTexpected=default(T);// TODO: Initialize to an appropriate valueTactual;target.Data=expected;actual=target.Data;Assert.AreEqual(expected,actual);Assert.Inconclusive("Verify the correctness of this test method.");}[TestMethod()]publicvoidDataTest(){Assert.Inconclusive("No appropriate type parameter is found to satisfies the type constraint(s) of T. "+"Please call DataTestHelper<T>() with appropriate type parameters.");}}}