I have three functions that looks something like this:
private Node GetNode(Node parentNode)
{
var node = new node();
switch (parentNode.NodeType)
{
case NodeType.Multiple: node = GetMultipleNode(parentNode)
case NodeType.Repeating: node = GetRepeatingNode(parentNode)
}
return node;
}
private Node GetMultipleNode(Node parentNode)
{
foreach (var child in parentNode.Children)
return GetNode(child);
}
private Node GetRepeatingNode(Node parentNode)
{
for (int i=0; i < parentNode.Count; i++)
return GetNode(new Node(i)); // Assume meaningful constructor for Node
}
Given that these three methods are mutually recursive, how does one go about unit testing them independently?
Mutual recursion is a variation recursion. Two functions are called mutually recursive if the first function makes a recursive call to the second function and the second function, in turn, calls the first one.
A recursive function typically contains a conditional expression which has three parts: A true-or-false-test that determines whether the function is called again, here called the do-again-test.
Mutual recursion is very common in functional programming, and is often used for programs written in LISP, Scheme, ML, and similar programming languages.
Normally you wouldn't need to test each method individually - you can just test that the top-level method does the right thing.
However if for some reason you want to test each method separately you can use dependency injection just as you would test any method that has dependencies. The only difference here is that the dependency is the object itself. Here is some example code to demonstrate the idea:
class NodeGetter : INodeGetter
{
public Node GetNode(Node parentNode)
{
return GetNode(parentNode, this);
}
public Node GetNode(Node parentNode, INodeGetter nodeGetter)
{
switch (parentNode.NodeType)
{
case NodeType.Multiple:
return nodeGetter.GetMultipleNode(parentNode, nodeGetter);
case NodeType.Repeating:
return nodeGetter.GetRepeatingNode(parentNode, nodeGetter);
default:
throw new NotSupportedException(
"Node type not supported: " + parentNode.NodeType);
}
}
public Node GetMultipleNode(Node parentNode, INodeGetter nodeGetter)
{
foreach (Node child in parentNode.Children)
{
return nodeGetter.GetNode(child);
}
}
public Node GetRepeatingNode(Node parentNode, INodeGetter nodeGetter)
{
for (int i = 0; i < parentNode.Count; i++)
{
// Assume meaningful constructor for Node
return nodeGetter.GetNode(new Node(i));
}
}
}
When testing for the nodegetter argument pass a mock.
I also changed your methods from private to public because it is better to only test the public interface of your class.
Well, you can't unit test them "independently" since they obviously depend on one another, but in principle you can certainly write separate tests for GetNode, GetMultipleNode, and GetRepeatingNode, assuming it makes sense to call each of these from the code that uses them. Sure, GetRepeatingNode calls GetNode, and so on, but that's no different from it calling some totally external function.
Incidentally, you might consider refactoring your design and use polymorphism instead of your NodeType enumeration. Just an idea :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With