views:

948

answers:

3

This question is self explanatory if you know how to use JMockit: How do I mock a method that has generics on it? I want to mock this method: public T save(T entity) but it always throws an exception like this:

mockit.RealMethodNotFoundForMockException: Corresponding real methods not found for the following mocks:
Object save(Object)
    at mockit.internal.RedefinitionEngine.modifyRealClass(RedefinitionEngine.java:130)
    at mockit.internal.RedefinitionEngine.modifyRealClass(RedefinitionEngine.java:88)
    at mockit.internal.RedefinitionEngine.redefineMethods(RedefinitionEngine.java:72)
    at mockit.Mockit.setUpMocks(Mockit.java:197)
    at com.mytest.MyTest.setUp(AdminManagerImplTest.java:83)
A: 

it does work for me, example

package a;

import junit.framework.TestCase;
import mockit.Mockit;

public class JMockitCoreExampleTest extends TestCase {

    public class MockMe {
     public T save(T t) {
      return null;
     }
    }

    public void testDoOperationAbc() {
     Mockit.redefineMethods(MockMe.class, SayThatYouMockMe.class);
                MockMe mock = new MockMe();
     System.out.println(mock.save("aaa"));
    }

    public static class SayThatYouMockMe {
     public T save(T t) {
      return t;
     }
    }
}

output

Loaded external tool: mockit.integration.junit3.JUnitTestCaseDecorator
Loaded external tool: mockit.integration.junit4.JUnit4ClassRunnerDecorator
aaa

maybe you are mocking hibernate's save method? if so try using jmockit's hibernate3emul.jar

01
A: 

I think your problem here might be that your generic type signature doesn't match that of the method you're trying to mock. Keep in mind that generic type information is not available at runtime, so JMockit only sees the methods that result from the erasure of the generic type information.

For example, suppose you have the following signature:

public <T> void foo(T param) {
  ...
}

The compiler translates this to:

public void foo(Object param) {
  ...
}

and this is the signature that appears in the bytecode, and what JMockit would see via reflection.

By contrast, the following signature:

public <T extends Map> foo(T param) {
  ...
}

erases to:

public void foo(Map param) {
  ...
}

So if, for example, your mock implementation uses the first signature while the real class uses the second, the underlying erasures would not match, and JMockit would not be able to find the method.

See http://today.java.net/pub/a/today/2003/12/02/explorations.html for more info

Kris Pruden
A: 

Maybe you have the same constellation I had:

I tried to Mock method <T> T merge(T t) in org.hibernate.ejb.EntityManagerImpl and got the same Mockit error.

Mockit.redefineMethods(EntityManagerImpl.class, EntityManagerImplMock.class);

My fault was that the merge method is NOT declared in org.hibernate.ejb.EntityManagerImpl but in its super class AbstractEntityManagerImpl. Now I have

Mockit.redefineMethods(AbstractEntityManagerImpl.class, EntityManagerImplMock.class);

with

public static class EntityManagerImplMock {
    public <T> T merge(final T o) {
        // nothing
        return o;
    }
}

and all works well.

Andreas Czakaj