Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Faking a Method of the Object Under Test

Is there a reason why you shouldn't create a partial fake of an object or just fake one method on the object that you are testing of it for the sake of testing another method? This might be helpful to save you from making an entire new mock object, or when there is an external dependency in the method you are faking which you can't reasonably get rid of and would like to keep out of all the other unit tests?

like image 847
Keith Pinson Avatar asked Jul 15 '11 19:07

Keith Pinson


3 Answers

The objects you want to do this for are trying to do too many things. In particular, if you have an external dependency, you would normally create an object to isolate that dependency. The Façade pattern is one example of this. If your objects weren't designed with testability in mind you may have to do some refactoring. Take a look at Michael Feathers' PDF on working with legacy code(PDF). He also has a book by the same title that goes into much more detail.

like image 59
Hugh Brackett Avatar answered Oct 13 '22 01:10

Hugh Brackett


It is a very bad idea to mock/fake part of a class to test another.

Doing this, you are not testing what the real code does in the conditions under test leading to unreliable test results.

It also increases the maintenance burden of the faked part of the class. If this is in effect for the whole test program, the fake implementation also makes other tests on the faked method harder.

You need to ask yourself why you need to fake out the part under test.

If it is because the method is accessing a file or database, then you should define an interface and pass an instance of that interface to the class constructor or method. This allows you to test different scenarios in the same test application.

If it is because you are using singletons, you should rethink your design to make it more testable: removing singletons will remove implicit dependencies and maintenance nightmares.

If you are using static methods/free-standing functions to access data in a registry or settings file, you should really move that out of the function under test and pass the data as a parameter or provide a settings provider interface. This will make the code more flexible and robust.

If it is to break a dependency for the purpose of testing (e.g. faking out a vector method to test a method in a matrix class) then you should not be faking that -- you should treat the code under test as what is defined by the class under test by its public interface: methods; pre-conditions, post-conditions, invariants, documentation, parameters and exception specifications.

You can use knowledge of the implementation details to test special edge cases, but trigger those through the main API, not by faking an implementation detail.

For example, suppose you faked std::vector::at() but the implementation switched to use operator[] instead. Your test would break or silently pass.

like image 29
reece Avatar answered Oct 12 '22 23:10

reece


If the method you want to fake is virtual (as in, not static and not final), then you can subclass your object in your test, override the method in the subclass, and exercise the subclass in the test. No mock-object libraries required.

(Ideally you should consider refactoring, this is not a great long-term solution. But it is a way to get legacy code under test so you can start the refactoring process more easily.)

like image 26
Nathan Hughes Avatar answered Oct 12 '22 23:10

Nathan Hughes