2012-04-17 17 views
1

ユニットテストで要求スコープ管理に関する多くの質問がありましたが、主に、スコープ管理をテストしないことがSpring Frameworkのタスクであり、正しく動作するように注意する必要があります。たとえば、アドバイスは、要求スコープをスレッドまたはプロトタイプタイプのスコープでXML構成ファイルに置き換えることです。ユニットテストでのスコープBean管理のリクエスト

ほとんどのテストでは、「要求」スコープが登録されていないことに関する苦情はなく、テストはうまく動作しています。しかし、私は十分ではない1つのケースがあります。私はリクエストスコープであるMyServiceでは、テストしたい

@Component 
@Scope("request") 
public class MyService { 

    @Autowired 
    private MyComponent component; 

    public void doSomething(String param) { 
     component.doTheThing(param); 
    } 
} 

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration({"classpath:my-scope-tweaks.xml"}) 
public class MyServiceTest { 

    @Autowired 
    private MyService service; 

    @Autowired 
    private MyComponent component; 

    @Test 
    public void test1() { 
     service.doSomething("aaa"); 

     assertEquals("AAA", component.getTheThing()); 
    } 

    @Test 
    public void test1() { 
     service.doSomething("bbb"); 

     assertEquals("BBB", component.getTheThing()); 
    } 

} 

は、ケースを、次の点を考慮します。 MyComponentもリクエストスコープです。

バリアントA

私はSimpleThreadScopeとリクエストスコープを交換した場合、それは内部的に含まれている可能性があるので、たとえばtest2()MyComponentから悪い結果を受け取ることができるので、その後に両方のテストで私は、MyServiceMyComponentの同じインスタンスを受け取ることになります

test1()以前のバリアントB

からいくつかの内部「ゴミ」私はプロトタイプのスコープとリクエストスコープを交換した場合 - 私は私のテスト方法がreceivinている場合になるだろうg異なるインスタンスMyComponentMyServiceと同じです。そのため、アサーションは実行できません。

したがって、すべてのリクエストスコープのBeanがtest1()メソッドの間だけ残って破棄されるような、テストメソッドに関連する要求スコープが必要です。したがって、次にtest2()の間に、それらは再び新たに作成されます。

可能ですか?

答えて

0

これはあなたが探しているものではないかもしれませんが、なぜSpringを使って最初にテストクラスを管理していますか?それは私に過労のように思える。単体テストの場合、DIコンテナは必要ありません。依存関係を模擬し、テストしているコンポーネントまたはサービスのカプセル化された機能に注目してください。

フィールド注入を使用している間は、これを行うことはできません。あなたはコンストラクタまたはメソッド注入に変換する必要があります。

+0

私は現時点でやっている統合テストの種類。小さなユニットテストの場合、私はDIを使用しませんが、このケースでは、はるかに大きくて多くの注射が現れます(例はより良く説明するために簡略化されています)ので、Springが通常行うことを手動ですべてやり直すのは残念です... – Laimoncijus

+1

あなたが今言っていることを見てください。しかし、あなたは 'Component'をどのように注入しているのか、まだコードの匂いがあります。あなたは、各テストのためにSpringに再度注入することを望んでいますが、プロトタイプのスコープ(Variant B)でさえ、これは起こりません。 Springはオブジェクトを1回だけ注入します。あなたが望むことをするためには、必要なオブジェクトのために毎回Contextと_ask_ Springのコピーを実際に持たなければなりません。また、 'Component'の別のコピーを必要とするのではなく、' MyService'オブジェクトを介してアサートする必要がある状態にアクセスできますか? –

+0

プロトタイプを使って 'MyService'を介して' MyComponent'にアクセスするのは正しいですから、私のテストクラスに '@ Autowire'を追加する必要はありません。 – Laimoncijus

0

@DirtiesContextでメソッドに注釈を付けることで、単体テストのすべてのメソッドに対して新しいコンテキストを受け取ることができます。これにより、1つの単体テストのアプリケーションコンテキストでBeanを操作し、他の単体テストに影響を与えないようにすることができます。

Documentation

@DirtiesContextでアノテートあなたの例:

@Component 
@Scope("request") 
public class MyService { 

    @Autowired 
    private MyComponent component; 

    public void doSomething(String param) { 
     component.doTheThing(param); 
    } 
} 

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration({"classpath:my-scope-tweaks.xml"}) 
public class MyServiceTest { 

    @Autowired 
    private MyService service; 

    @Autowired 
    private MyComponent component; 

    @Test 
    @DirtiesContext 
    public void test1() { 
     service.doSomething("aaa"); 

     assertEquals("AAA", component.getTheThing()); 
    } 

    @Test 
    @DirtiesContext 
    public void test2() { 
     service.doSomething("bbb"); 

     assertEquals("BBB", component.getTheThing()); 
    } 

} 

あなたのクラス内のテストメソッドのすべては、次のようにもちょうどクラスに注釈を付けることができ、新しいコンテキストが必要な場合:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration({"classpath:my-scope-tweaks.xml"}) 
@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD) 
public class MyServiceTest { 
    //Tests Here... 
} 
関連する問題