3

私のコードには、テスト時に痛みを引き起こす小さな食事療法がいくつかあります。小さな神々をバラバラにするのは、この演習にはあまりにも多くの努力であると仮定します。

x()通常の問題は、のメソッドをテストしたいのですFooが、のインスタンスを作成するにはFoo、Springのを満足させるためだけに存在するN(1 <N <10)のモックインスタンスを定義する必要があるということ@Autowireです。本番環境では、これらのフィールドが配線されていることを確認する必要があるため、これらをオプションにすることはオプションではありません。

私が見る可能な解決策:

  1. @Autowireどういうわけか、テスト期間中、一部のフィールドはオプションであることをSpringに伝えます
  2. テスト対象のコードが必要としない/必要としないものについては、呼び出し不可能なモックを渡します。

#1のやり方がわからないので、#2が道だと思います。私が好むのは、私が定義しなかったBeanのメソッド呼び出しに対して例外をスローするプロキシを返すBeanファクトリです。

したがって、不明なBeanの場合は、次のcreateメソッドを呼び出す必要があります。

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class MustNotCallMe {

    @SuppressWarnings( "unchecked" )
    public static <T> T create( final Class<T> type, final Class<?>... types ) {
        InvocationHandler handler = new InvocationHandler() {

            @Override
            public Object invoke( Object proxy, Method method, Object[] args ) throws Throwable {

                if( "equals".equals( method.getName() ) && Object.class.equals( method.getDeclaringClass() ) ) {
                    return proxy == args[0];
                }

                throw new UnsupportedOperationException( "You must not call " + method );
            }
        };

        Class<?>[] allClasses = new Class<?>[ types.length + 1 ];
        allClasses[0] = type;
        System.arraycopy( types, 0, allClasses, 1, types.length );

        return (T) Proxy.newProxyInstance( MustNotCallMe.class.getClassLoader(), allClasses, handler );
    }
}

このようなものはありますか?そうでない場合、Spring 3ユニットテストで自分のBeanファクトリをどのように注入しますか?

編集私はこの考えが言語の純粋主義者を混乱させることを知っています。現実だけが純粋になることはめったにありません。ここの誰かがステップアップして、ソフトウェアをリファクタリングするために必要なお金と手を私たちに与えてくれるなら、私たちはそれについて聞いてみたいです。それまでは、手作業をあまり必要とせずに問題を解決するソリューションは、特定の問題をはるかにうまく解決します:-)

BeanFactoryとは言うものの、必要なのは、スローすることはNoSuchBeanExceptionなく、代わりに「電話しないでください」プロキシを返すを作成する方法だけです。

4

2 に答える 2

1

ゴールデン パスは次のとおりです。テストで Spring を使用しないでください。単純なバニラ Java コードを使用して依存関係をセットアップするだけです。これが苦痛な場合は、コードをリファクタリングする方法の強力な指標があります。それは良いことです。呼び出されない依存関係については、すべてのメソッド呼び出しで爆発するモックを提供します。これを実現する簡単な方法は、この気の利いた Mockito 機能です: http://docs.mockito.googlecode.com/hg/org/mockito/Mockito.html#14

ダーティ パス: テストですべての依存関係をセットアップするのに耐えられないレガシーの沼地で立ち往生している場合 (マイナーゴッドの存在はその指標です)、SpringJUnit4ClassRunner+ Spring プロファイルを使用できます (使用する場合) Spring 3.1以降だと思います)。

これにより、たとえば、prod実稼働環境に使用するintegrationtestプロファイルと、上記のように呼び出してはならないすべての Bean をモックに置き換えるプロファイルを持つことができます。さまざまなチュートリアルの Google「春 + プロファイル」。それは簡単で、魔法のように機能します...しかし、交換したい豆のセットが固定されている場合にのみ適しています. 50 個のテストがあり、それぞれが 20 個の Bean の異なるサブセットを必要とし、呼び出し時に爆破する Bean に置き換えると、さらに悪化します。

地獄の道: Spring を使用しますが、特定の Bean セットを、テスト レベルごとにブローアップ オン コール Bean に置き換えます。これを行うには、単一の Bean を置き換えるための構成を含む特別なコンテキスト構成を用意します。実稼働 Bean と同じ名前/ID を持っている必要がありますが、呼び出しの実装で爆発します (必要に応じて Mockito を介して)。各テストで、次のような ContextConfiguration アノテーションを使用します。

@ContextConfiguration(locations = {"applicationContext.xml", "blowUpDemiGod42.xml",
    "blowUpDemiGod23.xml"})

これにより、blowUpDemiGod*.xmlファイル内の構成があなたの構成を上書きしますapplicationContext.xml

Javaコードを介してテストでBeanを提供できる、地獄のような道の軽い形があるかもしれません...わかりません。

于 2013-02-28T15:12:33.260 に答える
1

私はこの分野にはかなり慣れていませんが、Spring の全体的なアイデアは、テストやその他の環境の変更のために簡単に部品を交換できるということだと思いました。

概念は理解しているが、主要なものは何も実装していない (と思っている) 人の視点から見ると、これの何が問題なのか: 自動配線された各ピースはインターフェイスです。すべてのメソッドが何らかのエラー報告メカニズムを呼び出すだけのインターフェイスを実装するクラスを想像してみてください。すべてのメソッドで同じメカニズムを使用できます。そのようなクラスを (手動で) 作成するのは迅速で、エラーが発生しにくいはずです。これで「モック」が作成されました。これらが 10 個ある場合は、それらすべてに対してそのようなクラスを作成するのにそれほど時間はかからないはずです。

次に、特定の一連のテストに必要なこれらのモックのようなものを渡すスプリング構成ファイルを作成します。何かがモッククラスを呼び出すと、上記のエラーが吐き出されます。もちろん、さまざまなテスト環境用に、さまざまな構成にさまざまなモックを含めることができます。

ここで何が欠けていますか?

于 2013-02-28T14:48:52.110 に答える