2011-12-28 11 views
6

私は春のアプリケーションでサービスレイヤの単体テストを書いています。ここ
は、ここに私のサービスクラスユニットテストMockito

@Service 
    public class StubRequestService implements RequestService {  
     @Autowired 
     private RequestDao requestDao; 

     @Transactional(propagation = Propagation.REQUIRED, readOnly = true) 
     @Override 
     public Request getRequest(Long RequestId) { 
      Request dataRequest = requestDao.find(requestId); 
      return dataRequest; 
     } 
    } 

である私のテストクラスは

@RunWith(MockitoJUnitRunner.class) 
@ContextConfiguration(locations = { "/META-INF/spring/applicationContext.xml" }) 
public class StubRequestServiceTest { 

    @Mock 
    public RequestDao requestDao; 

    StubRequestService stubRequestService; // How can we Autowire this ? 

    @org.junit.Before 
    public void init() { 
     stubRequestService = new StubRequestService(); // to avoid this 
     stubRequestService.setRequestDao(dataRequestDao); 
     // Is it necessary to explicitly set all autowired elements ? 
     // If I comment/remove above setter then I get nullPointerException 
    } 

    @Test 
    public void testGetRequest() { 
     Request request = new Request(); 
     request.setPatientCnt("3"); 
     when(requestDao.find(anyLong())).thenReturn(request); 
     assertEquals(stubRequestService.getRequest(1234L).getPatientCnt(),3); 
    }  
} 

その作業罰金が、私が持っているいくつかの質問

  1. でどのようにすることができ、テストで我々Autowireサービスクラス?私はinit()メソッドでコンストラクタを使用してサービスオブジェクトを作成しています。
  2. サービスクラスのすべての要素をAutowireに設定する必要はありますか? ex StubRequestServiceの場合は、私が明示的にテストメソッドを呼び出す前に設定する必要があるRequestDaoをautowiredしていなければ、nullPointerExceptionrequestDaoとしてnullStubRequestService.getRequestメソッドとしています。
  3. ユニットテストの春のサービスレイヤーに従うと良い習慣は何ですか? (私が何か悪いことをしている場合)。
+0

あなたのテストがきれいになります。最後の編集をロールバックします。 –

+0

@JB:質問を編集する謝罪。私はちょうど正確で正確な情報を提供したかったのです。ありがとう – xyz

答えて

3
  1. テストが分かりやすくなると感じたら、スプリングコンテキストを初期化してそこからすべてのオブジェクトを取得できます。しかし、通常は、テスト用に個別にバネ構成のXMLファイルを作成する必要がありますので、推奨しません。

    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("testApplicationContext.xml"); 
    stubRequestService = (RequestService)applicationContext.getBean("myRequestServiceBean"); 
    
  2. (3)基本的に、私はお互いから合計孤立して自分のアプリケーションの各コンポーネントをテストすることを好むと私は、私は[1]で説明したものをお勧めしません理由です。それが何を意味するのか

は、完全は、それがアクセスしようとするすべてのものをモックアップしているときに、別の論理的なアプリケーションのスライスとテストのみそれを取るです。テストは、我々がここに書くことができるか、今

//Fetches stuff from some webservice and converts to your app domain POJOs 
class DataAccessLayer { 
    public void setWebservice(Webservice ws) {...}; 

    public MyObject getMyObject() {...}; 
} 

//Formats the domain POJOs and sends them to some kind of outputstream or stuff. 
class ViewLayer { 
    public void setOutputStream(OutputStream os) {...}; 

    public void viewMyObject(MyObject mo) {...}; 
} 

//Main entry point of our MyObject fetch-process-display workflow 
class Controller { 
    public void setDataAccessLayer(DataAccessLayer dal) {...}; 
    public void setViewLayer(ViewLayer vl) {...}; 

    public void showMyObject() { 
     MyObject mo = dal.getMyObject(); 
     ...some processing here maybe... 
     vl.viewMyObject(mo); 
    } 
} 

は、あなたが3つのクラスがあるとしましょうか?

  1. DataAccessLayerが適切に私たちのドメインオブジェクトにまで嘲笑 WSからオブジェクトを変換した場合のテスト。
  2. ViewLayerが与えられたオブジェクトを正しくフォーマットしているかどうかをテストし、に書き込んで、出力ストリームを作成します。
  3. テストControllerそれが正しくアップモックDataAccessLayerプロセスからオブジェクトを取得し、ViewLayerを嘲笑に送信した場合。
+0

テストでBeanをインスタンス化するために異なるコンテキストファイルを使用する具体的な理由はありますか?そして、例えば、ありがとう。それは本当に多くの助けになりました。 – xyz

+0

理由はありませんが、通常はテストと互換性がないということが起こります。たとえば、いくつかのJNDIリソースが必要です。データベースをロードしたり、テストでそれらを使用したりすることはありません。したがって、最後には、テスト用に別のコンテキストファイルを作成するほうが簡単であることに気づくだけです。 – bezmax

+0

はい、実際のDAOでサービスをテストしたくない理由があります。擬似DAOにサービスをテストさせたい。しかし、Maxの助言と鉱山に従ってください:単体テストサービスにSpringコンテキストを使用しないでください。 DAOテストではDatasource、SessionFactory、およびTxManagerを注入するSpringコンテキストが必要ですが、サービステストでは必要ありません。 –

7

あなたのテストは問題ありません。それは@ContextConfiguration注釈を持つ必要はありません。

Springのような依存性注入フレームワークの全体は、単純にインスタンス化し、モックの依存関係を設定し、そのメソッドを呼び出すだけで、ユニットテストサービスを実行できるようにすることです。

正しく実行しています。このような単体テストのためにSpringコンテキストを持つ必要はありません。そのため、ユニットテストと呼ばれています。実際の依存関係をすべて孤立させてテストします。

サイドノート:JUnitを使用していると仮定すると、assertXxxメソッドの引数を入れ替える必要があります。期待値は実際の値の前に来ます。アサーションが失敗し、「3を期待していたのではなく、6だった」というより、「6を期待していましたが、3でした」というメッセージが表示されたときに重要になります。

+0

回答と提案をありがとう。明示的にサービスオブジェクトを作成し、すべてのautowired依存関係を設定する必要がありますか?手動で設定するのではなく、オートワイヤードするように勧められています。 – xyz

+1

アプリケーションを実行しているとき、自動配線は正常です。単体テストでは、すべてのテストが自分自身の偽の依存関係を注入したいので、それは必要ないし、望ましくもありません。 –