How to deride a mockery of a class using final methods?

Let's say I have class A with

class A { final String foo() { // .. computing result, contacting database, whatever .. return "some computed value"; } // ... and a bazillion other methods, some of them final. } 

I now have class B with

 class B { String methodIWantToTest(A a) { String output = a.foo(); // ... whatever this method does, eg: output += "_suffix"; return output; } } 

How would I go for unit testing of this method? The reason foo() is final, because we do not want our classes to extend A to change its functionality. But at the same time a truly unit test method, I don't want it to stretch and run the actual A.foo() method.

Is there a way, say, to remove the last keyword and add annotation along the lines of @finalUnlessTest ? What would you suggest? Refactoring A to an interface would be very, very complex, as it was one of our central classes and, unfortunately, pretty was extremely connected.

Edit # 1 Sorry, forgot to mention, we are talking about Java. We do not use a mocking structure yet.

The answer is OK, so: wow. JMockit is just unbelievable and in my eyes a killer app for testing outdated code. Incredibly useful, especially in my case. Thanks! In my psuedo example, you would basically do something like the following:

 class AMock { final String foo() { return "myTestValue"; } } class Test extends TestCase { A mockedA; B b; protected void setUp() { Mockit.redefineMethods( A.class, AMock.class ); // this "pipes" all mocked methods from A to AMock mockedA = new A(); // NOT new AMock()!!! b = new B(); } public void testB() { assertEquals("myTestValue",mockedA.foo()); assertEquals("myTestValue_suffix",b.methodIWantToTest(mockedA)); } } 

Is this fricken cool or what?

+6
java unit-testing mocking legacy-code
source share
3 answers

You can try the JMockit mocking library.

+6
source share

I would remove "final" and just add the comment "Do not override this method !!". If you cannot trust employees to not follow simple instructions, they are still hopeless.

0
source share

The following code will also allow you to do this. I'm not saying this is good practice, but it is an interesting use (abuse?) Of anonymous classes.

 public class Jobber { public final String foo() { return fooFactory() ; } String fooFactory() { return "jobber" ; } public static void main(String[] args) { Jobber jobber = new Jobber() { String fooFactory() { return "prefix " + super.fooFactory() ;} } ; System.out.println(jobber.foo() ); } } 
0
source share

All Articles