2009-05-28 18 views
3

ユニットテストでSpringがEasyMockモックを注入しようとしています。私は私のテストを実行しようとすると、私はこのスタックトレースを取得Springを使ってEasyMockモックを注入すると、ClassCastExceptionが発生する

@Autowired 
@Qualifier("mockService") 
private Service service; 

public void testGetFoo() { 
    Foo foo = new Foo(); 

    expect(service.findFoo()).andReturn(foo); 
    replay(service); // <-- This is line 45, which causes the exception 

    // Assertions go here... 
} 

:私のユニットテストで

<bean id="mockService" class="org.easymock.EasyMock" factory-method="createMock" name="MockService"> 
    <constructor-arg index="0" value="my.project.Service"/> 
</bean> 

私はこれを持っている:私のapplicationContext.xmlをで

は、私はこれを持っています

java.lang.ClassCastException: org.springframework.aop.framework.JdkDynamicAopProxy 
at org.easymock.EasyMock.getControl(EasyMock.java:1330) 
at org.easymock.EasyMock.replay(EasyMock.java:1279) 
at TestFooBar.testGetFoo(TestVodServiceLocator.java:45) 

私は春とEasyMockの両方に非常に新しいですが、私に電話をしようと、エラーがEasyMockによって引き起こされているように私には思えますそれはEasyMockのインスタンスとみなされていますが、実際にはSpringによって作成された動的なプロキシです。私が理解しているように、動的プロキシはインターフェイスで定義されたメソッドのみを実装します。この場合はServiceのインターフェイスです。

私が理解できないことは、少なくともfrom what I readhere)ですが、私が達成しようとしていることは少なくとも可能であると思われます。

私の質問は:私は何をしていないのですか、何が間違っているのですか?

答えて

4

解決済み!

私は私のapplicationContext.xmlをでこれを見落としていました:自動的に「サービス」で終わる名前を持つすべてのBeanのためのプロキシオブジェクトを作成するために、春を引き起こし

<bean id="txProxyAutoCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> 
    <property name="beanNames"> 
     <list> 

      <value>*Service</value> 
      <!-- ^^^^^^^^  
       This is the problem! 
      --> 
     </list> 
    </property> 
    <property name="interceptorNames"> 
     <list> 
      <value>txAdvisor</value> 
     </list> 
    </property> 
</bean> 

を...。

私の解決策は、ワイルドカードを使用する代わりに明示的にBeanを一覧表示することでした。しかし、これは私にとってはやや脆いようです。だから誰もが、サービス豆 FooService以外)を指定する方法を知っていれば、私は感謝しています。

1

ここで何か奇妙です。 SpringとEasyMockの両方を素早くマスタリングしています。 autoproxies、工場のメソッド、あなたがSpringの能力に深く関わっていることを示す良い兆候。

まだ、擬似ビーンをクラスにまったく注入するのは奇妙です。あなたは大きな理由があるかもしれませんが、私にはそれはコードの匂いです。実際のサービスでテストクラスに配線することだけを検討し、必要に応じてモックオブジェクトを初期化することをお勧めします。依存関係のないモックオブジェクトを作成するために、Javaで3行、XMLで3行(なぜなら1行をリセット)を費やすのはなぜですか?ちょうどサービスサービス=(サービス)createMock(Service.class)と言う。あなたが必要とする方法でそれらを作成し、期待値を設定し、注入し、使用し、破棄するようアドバイスします。モデルでは、モックオブジェクトを使用するたびにモックオブジェクトをリセットすることを覚えておく必要があります。新しいオブジェクトを作成するだけでは不明です。

もちろん、これはスタイルの問題であり、正しさの問題ではないので、必要に応じて無視してください。

public static <T> T unwrap(T proxiedInstance) { 
    if (proxiedInstance instanceof Advised) { 
    return unwrap((T) ((Advised) proxiedInstance).getTargetSource().getTarget()); 
    } 

    return proxiedInstance; 
} 

(注)複数のプロキシは、実際のターゲットに巻き付けてきた最悪の場合のようにrecusiveコール:

+0

私は簡単に理解できるように、投稿する前に私の例をやや簡略化しました。 テスト対象のクラスは、その名前に基づいて実行時に特定のBeanをアプリケーションコンテキストから取得することになります。そのBeanをXMLファイルのモックとして定義するのは明らかでした。 まだ、私はあなたの要点を理解しており、あなたは正しいです。私はいくつかのものが混じっていて、あまりにも遠くに行ったと思う。 – KaptajnKold

+0

インテグレーションテストアドバイスの実行や配線を行う場合に便利です。このようにすることができます。トランザクションが正しく適用されているかどうかを確認します。 –

6

また、その後、正常な動作を定義するために春プロキシからEasyMockプロキシをアンラップするためのヘルパーメソッドを作成することができます。

+0

私はその方法が本当に好きです! –

+0

私はもっとアップフォート –

1

私はこの質問が古いことを知っていますが、私は同様の問題を探しています。

問題は、春はモックオブジェクトのタイプを知らないということです。使用する方法は、次のようになります。

public static <T> T createMock(final Class<T> toMock) { 
    return createControl().createMock(toMock); 
} 

春は、コンストラクタ引数(私がチェックした少なくとも前回)からTを導出するために十分にスマートではありませんので、返されるオブジェクトはタイプjava.lang.Objectであると考えて。結果として、作成されたプロキシはmy.project.Serviceを実装しないため、注入することはできません。

答えはSpringに必要なタイプを伝えることです。

関連する問題