Как мне смоделировать метод с универсальными объектами в JMockit? - PullRequest
3 голосов
/ 02 февраля 2009

Этот вопрос не требует пояснений, если вы знаете, как использовать JMockit: как мне смоделировать метод, который имеет обобщенные элементы? Я хочу издеваться над этим методом: public T save (T entity), но он всегда выдает исключение вроде этого:

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)

Ответы [ 4 ]

2 голосов
/ 17 марта 2015

Просто ради полноты:

У меня была похожая проблема с Java 1.7 в режиме Java 1.6, TestNG и jMockit 1.5 и 1.16 с использованием метода MockUp <...> класса.

Мой класс:

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

Издеваемый метод:

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

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

Оригинальная попытка издеваться:

    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));
        }
    };

Я получил похожее исключение. После добавления дополнительного универсального параметра после public мой тестовый пример, наконец, прошел успешно:

    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));
        }

    };
1 голос
/ 02 февраля 2009

у меня работает, пример

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;
        }
    }
}

выход

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

может быть, вы издеваетесь над способом сохранения в hibernate? если это так, попробуйте использовать hibernate3emul.jar из jmockit

0 голосов
/ 28 октября 2009

Возможно, у вас есть то же созвездие, что и у меня:

Я попытался смоделировать метод <T> T merge(T t) в org.hibernate.ejb.EntityManagerImpl и получил ту же ошибку Mockit.

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

Моя ошибка заключалась в том, что метод слияния НЕ объявлен в org.hibernate.ejb.EntityManagerImpl, а в его суперклассе AbstractEntityManagerImpl. Теперь у меня есть

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

с

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

и все хорошо работает.

0 голосов
/ 03 февраля 2009

Я думаю, что ваша проблема может заключаться в том, что ваша сигнатура универсального типа не соответствует методу, который вы пытаетесь смоделировать. Помните, что информация об универсальном типе недоступна во время выполнения, поэтому JMockit видит только те методы, которые возникают в результате удаления информации об универсальном типе.

Например, предположим, у вас есть следующая подпись:

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

Компилятор переводит это на:

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

и это подпись, которая появляется в байт-коде, и то, что JMockit увидит через отражение.

Напротив, следующая подпись:

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

стирает до:

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

Так что, если, например, ваша фиктивная реализация использует первую сигнатуру, а реальный класс использует вторую, базовые стирания не будут совпадать, и JMockit не сможет найти метод.

Подробнее см. http://today.java.net/pub/a/today/2003/12/02/explorations.html

...