I find myself falling into this pattern quite a lot, I write a class composed of very small methods which are completely exercised by my unit tests. Then I find I need to build another method that calls these methods and I have to write a more complicated unit test for that – a simple example would be illustrative:
namespace FooRequest
{
static public class Verifier
{
static public bool IsValid(string request)
{
return (!IsAllCaps(request) && !ContainsTheLetterB(request));
}
static internal bool IsAllCaps(string request)
{
return (request.Equals(request.ToUpper()));
}
static internal bool ContainsTheLetterB(string request)
{
return request.ToLower().Contains("b");
}
}
}
For code I’d write unit tests to cover the two internal methods like this:
namespace UnitTest
{
using Microsoft.VisualStudio.TestTools.UnitTesting;
using FooRequest;
public class VerifierTest
{
[TestClass]
public class ContainsTheLetterB
{
[TestMethod]
public void ShouldReturnTrueForStringContainsB()
{
Assert.IsTrue(Verifier.ContainsTheLetterB("burns"));
}
[TestMethod]
public void ShouldReturnFakseForStringDoesNotContainB()
{
Assert.IsFalse(Verifier.ContainsTheLetterB("urns"));
}
}
[TestClass]
public class IsAllCaps
{
[TestMethod]
public void ShouldReturnTrueForStringIsAllCaps()
{
Assert.IsTrue(Verifier.IsAllCaps("IAMALLCAPS"));
}
[TestMethod]
public void ShouldReturnFakseForStringDoesNotContainB()
{
Assert.IsFalse(Verifier.IsAllCaps("IAMnotALLCAPS"));
}
}
}
}
For the public method I really just want to test “if the methods you call return false, then return false” – it’s annoying that I have to set up the input in such a way to force my internal methods to return true or false – my test for this method shouldn’t care about the internal methods it calls (right?)
[TestClass]
public class IsValid
{
[TestMethod]
public void ShouldReturnFalseForInvalidStringBecauseContainsB()
{
Assert.IsFalse(Verifier.IsValid("b"));
}
[TestMethod]
public void ShouldReturnFalseForInvalidStringBecauseIsAllCaps()
{
Assert.IsFalse(Verifier.IsValid("CAPS"));
}
[TestMethod]
public void ShouldReturnTrueForValidString()
{
Assert.IsTrue(Verifier.IsValid("Hello"));
}
}
Obviously for this example, that’s not too bad, but when there are lots of internal methods and the input is non-trivial to configure, testing my public “Is This Input Valid” method gets complicated.
Should I create an interface for all my internal methods then stub it out for the tests or is there a neater way?
I was typing a comment but it got to be too big. I think you're on the borderline of violating SRP but you are definitely violating the open/closed principle. If you need to change the way you verify strings, your verifier class needs to be modified.
I would approach this a bit different than @seldary would, but not by much...
public interface IStringRule
{
bool Matches(string request);
}
public class AllCapsRule : IStringRule
{
public bool Matches(string request)
{
//implement
}
}
public class IsContainingBRule : IStringRule
{
public bool Matches(string request)
{
//implement
}
}
public class Verifier
{
private List<IStringRule> Rules;
public Verifier(List<IStringRule> rules)
{
Rules = rules;
}
public bool IsValid(string request)
{
return (!Rules.Any(x=>x.Matches(request) == false));
}
}
Now your verifer is open to extension, but closed to modification. You can add as many new rules as you like and the implementation doesn't change. Testing the verifier is as simple as passing in some mock string rules that return arbitrary true and false values and making sure that the verifier returns the appropriate result.
Each IStringRule gets tested separately as you were doing.
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