Question

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)
Was it helpful?

Solution

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

OTHER TIPS

Just for the sake of completeness:

I had a similar issue with Java 1.7 in Java 1.6 mode, TestNG and jMockit 1.5 and 1.16, using in-method MockUp<...> of a class.

My class:

public class MyCache extends AbstractLazyCache<ExchangeObject> {...}

The mocked method:

 public abstract class AbstractLazyCache<CachedObject> extends AbstractCache {
      // ...

      protected void putCachedObject(String tenantId, String objectId, CachedObject o, Date expiryDate) {...}
  }

Original mocking attempt:

    new MockUp<MyCache>() {
        // invoked once manually, once on expired cache
        @Mock(invocations = 2)
        public void putCachedObject(Invocation inv, String tenantId, String objectId,
                RangeExchange o, Date expiryDate) {
            // expire one second in the future
            inv.proceed(tenantId, objectId, o, new Date(System.currentTimeMillis() + waitTimeMillis));
        }
    };

I got a similar exception. By adding an additional generic parameter after public, my test case finally succeeded:

    new MockUp<MyCache>() {
        // invoked once manually, once on expired cache
        @Mock(invocations = 2)
        public <RangeExchange> void putCachedObject(Invocation inv, String tenantId, String objectId,
                RangeExchange o, Date expiryDate) {
            // expire one second in the future
            inv.proceed(tenantId, objectId, o, new Date(System.currentTimeMillis() + waitTimeMillis));
        }

    };

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

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top