So, we currently have a class that's split into ten partial classes (never seen that) and I need to write a unit test for one of the methods (Method A
) in that class. Method A, however, references a method (Method B
) from the same partial class (different area in project) that I need to mock. Is this possible?
One of the partial classes inherits from an interface named for the class, so I'm wondering if I can just add Method B
to said interface to be able to mock it, or if Method A
would even understand the mock when testing. Maybe mock both methods? But I figure we'd have to inject said interface into the class, but if it's partial, can we even do that? We use Moq and NSubstitute.
I'm spinning wheels as I'm new to unit testing and this area of our legacy code is apparently not too good when it comes to being testable so any help/guidance is greatly appreciated.
As you pointed out, for this to be properly testable, MethodB
or its functionality would need to be an injectable resource, so an alternative way with minimum changes would be to mark the method as virtual
and create a utility class that allows you to override it with your own implementation for testing purposes:
//Partial containing MethodA
public partial class PartialClass
{
public void MethodA()
{
MethodB();
}
}
//Partial containing MethodB
public partial class PartialClass
{
//Notice it is now virtual
public virtual void MethodB()
{
Console.WriteLine("Original Method B");
}
}
//Utility class
public class PartialClassTestHarness : PartialClass
{
//Custom MethodB logic for testing
public override void MethodB()
{
Console.WriteLine("New Method B");
}
}
Test:
var partialClass = new PartialClass();
partialClass.MethodA();
var harness = new PartialClassTestHarness();
harness.MethodA();
Output:
Original Method B
New Method B
You can get fancy and make a constructor in your utility class with an Expression
or Action
that can represent the execution of the method so you can inject your behavior for different tests, but that is beyond the scope of your question.
Obviously, the ideal way to go about this would be to refactor the original class for dependency injection but that can potentially result in lots of breaking changes that you would need to address and retest. Sometimes the ideal way is not really the best way, so...