Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UnitTests: how to test dependent methods where mocking is unfeasible?

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.

like image 742
froitag Avatar asked Dec 04 '13 16:12

froitag


People also ask

Should all dependencies be mocked in a unit test?

Correct. You should mock things that depend on anything persistent or external in order to prevent the test from depending on anything persistent or external.

When should you not use a mock?

Only use a mock (or test double) “when testing things that cross the dependency inversion boundaries of the system” (per Bob Martin). If I truly need a test double, I go to the highest level in the class hierarchy diagram above that will get the job done. In other words, don't use a mock if a spy will do.

Why mocking is necessary in unit testing?

What is mocking? Mocking is a process used in unit testing when the unit being tested has external dependencies. The purpose of mocking is to isolate and focus on the code being tested and not on the behavior or state of external dependencies.

What is stub and mock?

Stub: a dummy piece of code that lets the test run, but you don't care what happens to it. Substitutes for real working code. Mock: a dummy piece of code that you verify is called correctly as part of the test. Substitutes for real working code.


Video Answer


1 Answers

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.

like image 138
Daniel Mann Avatar answered Oct 02 '22 04:10

Daniel Mann