Reputation: 34798
What's the recommended way to cover off unit testing of generic classes/methods?
For example (referring to my example code below). Would it be a case of have 2 or 3 times the tests to cover testing the methods with a few different types of TKey, TNode classes? Or is just one class enough?
public class TopologyBase<TKey, TNode, TRelationship>
where TNode : NodeBase<TKey>, new()
where TRelationship : RelationshipBase<TKey>, new()
{
// Properties
public Dictionary<TKey, NodeBase<TKey>> Nodes { get; private set; }
public List<RelationshipBase<TKey>> Relationships { get; private set; }
// Constructors
protected TopologyBase()
{
Nodes = new Dictionary<TKey, NodeBase<TKey>>();
Relationships = new List<RelationshipBase<TKey>>();
}
// Methods
public TNode CreateNode(TKey key)
{
var node = new TNode {Key = key};
Nodes.Add(node.Key, node);
return node;
}
public void CreateRelationship(NodeBase<TKey> parent, NodeBase<TKey> child) {
.
.
.
Upvotes: 11
Views: 8935
Reputation: 27495
A lot depends on your generic constraints. If one or more of type parameters requires an interface or base class constraint, there is now a dependency on the interface contract. Since the logic of your class may partially depend on the behavior of the class implementing the interface, you may need to mock the interface in various ways to exercise all of your logical pathways. For instance, if you have T: IEquatable<T>
, you'll need to use a type with meaningful equality behavior, like an int.
Upvotes: 0
Reputation: 17837
It could really depends on your code but there are at least two things to think about :
Upvotes: 2
Reputation: 3201
To unit test an open production type, create a test code type that derives from the open type - then test that type.
public class TestingTopologyBase : TopologyBase<KeyType, NodeType, RelationshipType> ...
In the TestingTopologyBase class, provide a base implementation of any abstract methods or anything else that is mandatory.
These Testing[ProductionType] implementations are often excellent places for your unit test code to sense what the generic type under test is actually doing. FOr instance, you can store away information that can later be used by your unit test code to inspect what went on during the test.
Then in your unit test methods, create instances of the TestingTopologyBase class. This way, you test the generic type in isolation from any production types that derive from it.
Example:
[TestClass]
public class TopologyBaseFixture {
[TestMethod]
public void SomeTestMethod() {
var foo = new TestingTopologyBase(...);
...test foo here
Upvotes: 1
Reputation: 4401
You could use a mocking framework to verify expected interaction between the your class and the generic type. I use Rhino Mocks for this.
Upvotes: 1
Reputation: 5773
I usually create a DummyClass for test purpose to pass as a generic argument (in your case you should create 3 class) and the I test the class (TopologyBase) once.
Testing with different generic types doesn't make sense, since the generic type should not break the ToopologyBase class.
Upvotes: 5