2012-02-08 14 views
2

とJPA CriteriaBuilder私がチェックし、特に厄介なJMockを(持っている)私はMockitoに移行することをJPAクエリのブロック:モックMockito

Mockery jMock = new Mockery(); 
final EntityManager fakeEntityManager = jMock.mock(EntityManager.class); 
final CriteriaBuilder fakeCriteriaBuilder = jMock.mock(CriteriaBuilder.class); 
final CriteriaQuery<String> fakeCriteriaQuery = jMock.mock(CriteriaQuery.class); 
jMock.checking(new Expectations() {{ 
    oneOf(fakeEntityManager).getCriteriaBuilder(); will(returnValue(fakeCriteriaBuilder)); 
    oneOf(fakeCriteriaBuilder).createQuery(String.class); will(returnValue(fakeCriteriaQuery)); 
    oneOf(fakeCriteriaQuery).from(Archiveusergrouplicences.class); 
    oneOf(fakeCriteriaQuery).select(with(any(Selection.class))); 
    oneOf(fakeCriteriaBuilder).isNotNull(with(any(Expression.class))); 
    oneOf(fakeCriteriaQuery).where(with(any(Expression.class))); 
    oneOf(fakeEntityManager).createQuery(fakeCriteriaQuery); 
    // Return an empty resultset 
}}); 

テストされているコードは次のようになります。

CriteriaBuilder builder = entityManager.getCriteriaBuilder(); 
CriteriaQuery<String> criteria = builder.createQuery(String.class); 

Root<Archiveusergrouplicences> institution = criteria.from(Archiveusergrouplicences.class); 
criteria.select(institution.get(Archiveusergrouplicences_.usergroupid));  
criteria.where(builder.isNotNull(institution.get(Archiveusergrouplicences_.usergroupid))); 

List<String> result = entityManager.createQuery(criteria).getResultList(); 

私はthis question on mocking buildersを見つけました。これは、モックのCriteriaBuilderの部分を解決する方法になります。私の主な問題は、擬似オブジェクトを別のモックの.thenReturn()値として使用することです.Mockitoはそれを許可していないようです。たとえば、行のために:

CriteriaQuery<String> criteria = builder.createQuery(String.class); 

私はこのように、モックCriteriaQueryオブジェクトを返すようにしたい:私は行くかもしれない方法

The method thenReturn(Query) in the type OngoingStubbing is not applicable for the arguments (CriteriaQuery)

CriteriaQuery<String> fakeCriteriaQuery = mock(CriteriaQuery.class, RETURNS_DEEP_STUBS); 
when(entityManager.createQuery(anyString())).thenReturn(fakeCriteriaQuery); 

これは構文エラーがスローされますこのコードをテストする方法、またはテストする方法を改善する方法について

+2

ORM全体を嘲笑することが本当に問題の価値があるかどうか、またはそれを使用するほうが簡単かどうかという質問です。テスト用のメモリ内データベース。 http://www.dbunit.org/これもまた過去において有用であることが証明された。 –

+0

他のすべてのテストは機能的です(テストデータベースとdbunitに似たものを使用します)。私が移行しようとしているテストの目的は、予期しない例外が発生した場合、DAOはNoResultsExceptionを呼び出し元に返します。私は例外が、クエリ中にデータベースがダウンするようなシナリオや、テストされている場合にはJPAフレームワークによって返されるNPEのようなシナリオに依存すると思います。 – seanhodges

+0

テストをさらに進めれば、それを書く良い方法があるかもしれません。 funcテストを使用して、クエリを実行する前にテーブルを削除することは、NPEを強制するよりも良いアプローチかもしれません。 – seanhodges

答えて

1

すぎCriteriaQueryをmockitoする必要があります - 限り、あなたが右の引数を設定して!私が主張しようとしていた:私は実際に何を望むか

when(entityManager.createQuery(anyString())).thenReturn(fakeCriteriaQuery); 

がクラスに渡すことでした:

when(fakeCriteriaBuilder.createQuery(String.class)).thenReturn(fakeCriteriaQuery); 

エラーが、私は私の期待を台無しにしていた私に告げるのMockitoの不可解な方法でした。

しかし、私は最初に書かれたものを翻訳するのではなく、このテストを書き直すことがあります。いくつか指摘したように、この方法でライブラリを嘲笑することを避けるほうがよい場合が多く、チェックされる条件はむしろあいまいです。

+1

Mockitoには、「RETURNS_DEEP_STUBS」というデフォルトの回答がありますが、これはBuilder APIにとってはあまり役に立ちません。モックを返す模擬テストは、テストの匂いに似ています。あなたのユニットテストはメソッドのインプリメンテーションがあまりにも多く結合しているので、ホワイトボックステストです!私は、H2などの統合テストについて考えることを強くお勧めします。 Antonio Goncalves、JPAのJSR専門家がこの問題に関する興味深い記事を書いたhttp://agoncal.wordpress.com/2012/01/16/wytiwyr-what-you-test-is-what-you-run/ – Brice

0

あなたのようなjMock CriteriaQuery

final CriteriaQuery<String> fakeCriteriaQuery = jMock.mock(CriteriaQuery.class); 

あなたはそれはあなたが他のモックからモックを返すことができ判明

final CriteriaQuery<String> fakeCriteriaQuery = mock(CriteriaQuery.class); 
+1

コミュニティを嘲笑する小さなお知らせ:** [自分が所有していないタイプを模倣しないでください](http://www.google.fr/search?q=don't%20mock%20type%20you%20don ' t%20own)**代わりに統合テストを書く! – Brice

+0

@ブリス:このポインタありがとう。質問自体に私のコメントで示したように、これは悪い考えであると感じました。さて、私はこの感情をサポートするための参考資料を持っています。再度、感謝します! –

+0

ユニットテストでそれをすることができないことがありますか? –