5

I'm fairly new to UnitTesting and just encountered a situation I don't know how to handle and I'd appreciate any hints :)

The situation is as follows, imagine two methods:

// simple standalone method public bool HelperMethod(string substr) { return substr.Equals("abc"); } // complex method making (multiple) use of HelperMethod public bool ActualMethod(string str) { for (var i=0; i<str.Length; i++) { var substr = str.Substring(i, 3); if (HelperMethod(substr)) return true; } return false; } 

HelperMethod functions without dependencies, ActualMethod however depends on HelperMethod and therefore its UnitTest will fail if HelperMethod's one does.

Actually, if I'm not mistaken, this is where mocking/dependency injection should come to rescue.

But in this specific case, I'd like to test several (arbitrary large) edge-cases (which may not be necessary for the code above, but the actual ActualMethod implementation is a part of fairly complex syntax parser). Since HelperMethod is called multiple times in each ActualMethod call, I would have to mock hundreds of HelperMethod calls for my test which just seems unbearable (now just imagine the number of needed HelperMethod calls would be quadratic to the input..).

My question is: how could one elegantly test a method that delegates a huge number of calls to another method? Should I really mock all these delegate calls? Or am I maybe allowed to make the method test depend on the other method's test (sth. like Assert(HelperMethodPassed)? Or is there no way around changing the design of the implementation?

Unfortunately inlining HelperMethod in the ActualMethod isn't possible because other methods rely on it as well.

Thanks in advance, I'd really appreciate any help! :)

PS: The project that is being tested is written in C# and I'm currently using the MSTest framework (but I'm open for switching to another framework if this solves the problematic).

Edit: explicitly marked HelperMethod and ActualMethod as public.

3 Answers 3

6

In general, if code is difficult to isolate for testing, it points to a design problem.

Since you're calling HelperMethod a bunch of times in the context of the method you're trying to test, it sounds like the problem is that ActualMethod is doing too much. You can make it more unit testable by breaking ActualMethod down into smaller methods that take the output of HelperMethod as a parameter, and then unit testing each of those individual methods.

Of course, you'll want to ensure that HelperMethod is unit tested as well!

As other folks have stated, if the HelperMethod is private and not used outside the class, then you can ignore the above advice and ensure that HelperMethod is tested by making sure that you cover every reasonable permutation of test cases via the public interface (e.g. ActualMethod). Fundamentally, though, if HelperMethod contains complex logic, it should probably be unit tested independently.

Sign up to request clarification or add additional context in comments.

7 Comments

If you pick them apart at that point, then you just have to glue them back together somewhere else. I agree with your (implicit) statement that you have to design your abstractions for testing, but this seems like a 'how do I test my privates' problem.
Ahh, true. I was thinking of it as a public "helper" method, since the OP said that other methods rely on it. If it's private, then yeah. I'll update my answer accordingly. :)
I don't know if its private, but its being used that way. I don't think the OPs simplified example is all that helpful.
Agreed. Well, I updated my answer so it covers both bases. Thanks for the input!
Ok I get your point. But as @RichMelton already said if you pick them apart one will probably have to glue them together aftewards. This may lead to the exact same problem just at a different point. But as I interpret this whole discussion, there doesn't exist a proper solution to this exact problem. One just needs to keep the possibility for isolation in mind during design and this problem will hopefully never occur. I think that's it, thanks for sharing your knowledge!
|
4

If MethodHelper is an implementation detail and is consequently a private method in the same class as ActualMethod then I don't see a reason to test it seperately from ActualMethod. You should be able to achieve full coverage by testing ActualMethod.

2 Comments

I didn't know that private methods don't need to be unit tested! Thank you for that insight! Nice blog post from Peter Provost to back up this decision: peterprovost.org/blog/2012/05/31/… Basically he comes to the conclusion that unit-testing private implementation details prevents the developer from free refactoring and should therefore be avoided just as you said. Nonetheless it is assumed that HelperMethod from above is publicly accessible (edited the original post). But thanks for this hint!
You test private methods by testing the public methods :)
0

What you can do is:

  • Test HelperMethod so that all possible invocations from ActualMethod are covered in the unit tests.
  • Then assume that HelperMethod works and do not mock it, but use the actual implementation if you can guarantee that there aren't any side effects.

If the tests for HelperMethod fail, you can consider anything that ActualMethod does as undefined behavior, so it is not relevant if these tests pass or fail.

2 Comments

Unfortunately, this is what I was trying to circumvent. Making the ActualMethod test fail if the HelperMethod test fails may lead to confusion and inefficiency, e.g. if one encounters the error and starts debugging ActualMethod just in order to find out that it's HelperMethod's fault. Or do you think in this specific case (whole bunch of delegate calls where mocking is unfeasible), this kind test dependency is ok to have?
@AndréFreitag do not make the ActualMethod test fail, just ignore the results :)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.