4

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

4 に答える 4

2

完全を期すために:

クラスのインメソッド MockUp<...> を使用して、Java 1.6 モード、TestNG、jMockit 1.5 および 1.16 の Java 1.7 で同様の問題が発生しました。

私のクラス:

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

    };
于 2015-03-17T16:00:57.090 に答える
0

ここでの問題は、ジェネリック型のシグネチャが、モックしようとしているメソッドのシグネチャと一致しないことだと思います。ジェネリック型情報は実行時に利用できないことに注意してください。そのため、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) {
  ...
}

したがって、たとえば、モック実装が最初の署名を使用し、実際のクラスが 2 番目の署名を使用する場合、基になる消去が一致せず、JMockit はメソッドを見つけることができません。

詳細については、 http://today.java.net/pub/a/today/2003/12/02/explorations.htmlを参照してください。

于 2009-02-02T21:04:45.440 に答える
0

多分あなたは私が持っていたのと同じ星座を持っています:

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

すべてがうまく機能します。

于 2009-10-28T13:40:54.213 に答える