The best solution to mocking is to have the machine do all the work with automated specification-based testing. For Java, see ScalaCheck and the Reductio framework included in the Functional Java library. With automated specification-based testing frameworks, you supply a specification of the method under test (a property about it that should be true) and the framework generates tests as well as mock objects, automatically.
For example, the following property tests the Math.sqrt method to see if the square root of any positive number n squared is equal to n.
val propSqrt = forAll { (n: Int) => (n >= 0) ==> scala.Math.sqrt(n*n) == n }
When you call propSqrt.check()
, ScalaCheck generates hundreds of integers and checks your property for each, also automatically making sure that the edge cases are covered well.
Even though ScalaCheck is written in Scala, and requires the Scala Compiler, it's easy to test Java code with it. The Reductio framework in Functional Java is a pure Java implementation of the same concepts.