現在、学校ではかなり大きなプロジェクトに取り組んでいます。しかし、Javaでのテストではあまりうまく説明できなかったので、思っていたようにTDDを実際には使いませんでした。
protected EntityManager getEntityManager() {
return EntityController.getEntityManager();
}
// Get all exam skeletons from the DB
@Override
public List<ExamSkeleton> getAllSkeletons() {
EntityManager entityManager = getEntityManager();
try {
TypedQuery<ExamSkeleton> query = entityManager.createQuery("SELECT NEW ExamSkeleton (s.id, s.filename, s.course, s.visible) FROM ExamSkeleton as s", ExamSkeleton.class);
List<ExamSkeleton> skeletons = query.getResultList();
return skeletons;
} catch (IllegalArgumentException exception) {
LOGGER.error(exception);
}
return Collections.emptyList();
}
だから私の質問は、Mockitoを使用してこの方法をどのようにテストするのですか?
回答 2 件
1)EntityManagerをコントローラーに関連付けないでください:
return EntityController.getEntityManager();
設計の観点からは、望ましくありません。低層と高層を混在させないでください。
getAllSkeletons()
のテストに関して 、この結合により、ユニットテストの設定と書き込みが難しくなります。2)実際のメソッドにはテストするロジックはありませんが、例外の場合:クエリを作成して実行し、結果を返すだけです。
単体テストではなく、統合テスト(DBレイヤーのモックなし)に適しています。
単体テストが複雑になり、あまり価値がないので。
Mockitoで何が得られるのか、私はお勧めしません。
EntityManager
を作る テスト対象のクラスの依存関係:インジェクションの有無。
単体テストで、この依存関係をモックします。
次のようになります。@Mock EntityManager entityManagerMock; @Test public void getAllSkeletons(){ TypedQuery<ExamSkeleton> queryByMock = (TypedQuery<ExamSkeleton>) Mockito.mock(TypedQuery.class); Mockito.when(entityManagerMock.createQuery("SELECT NEW ExamSkeleton (s.id, s.filename, s.course, s.visible) FROM ExamSkeleton as s")) .thenReturn(queryByMock); List<ExamSkeleton> skeletons = new ArrayList<>(); Mockito.when(queryByMock.getResultList()) .thenReturn(skeletons); Foo foo = new Foo(); foo.setEntityManager(entityManagerMock); // action List<ExamSkeleton> actualSkeletons = foo.getAllSkeletons(); // assertion Assert.assertSame(skeletons, actualSkeletons); }
呼び出しの流れを説明するだけのこの種のコードは実際には書かないでください。
これは、テストを非常に脆弱にし、リグレッションをキャッチすることはほとんどありません。
アプローチ1:コードをテストするそのまま
ザ・
アプローチ2:懸念の分離とテストの容易さのためのリファクタリングgetEntityManager
メソッドはプライベートであり、静的メソッドを呼び出します。したがって、現状では、PowerMockitoを使用してEntityManager
の模擬インスタンスを提供する必要があります。 あなたのテストで。例えば:ただし、たとえば、エンティティマネージャの作成をファクトリに外部化することにより、テストと設計の観点から物事を単純化できます。
次に、
EntityManagerFactory
のインスタンスを注入しますgetAllSkeletons()
を含むクラスに (つまり、テストするクラス)。これを行う最も簡単な方法は、コンストラクター引数として宣言することです。これで、vanilla mockitoを使用してこのコードをテストできます。例えば: