26

私のプロジェクトでは、単体テストを行うのに問題があります。1 つの問題は、統合テストを実行するだけで、作成がはるかに高速になり、コンポーネントが実際に連携して動作することもテストされることです。新しい「アルゴリズム」などの単体テストは、はるかに簡単に思えます。単体テストサービスクラスは、間違っていて役に立たないと感じています。

私はmockitoを使用してSpringデータリポジトリをモックしています(したがってDBアクセス)。問題は、モックされたリポジトリにメソッド呼び出し getById でエンティティ A を返すように指示すると、明らかにそれが返され、サービスもそれを返すことです。はい、サービスはいくつかの余分な処理を行いますが、(休止状態からの) 遅延コレクションのロードなど、非常に小さな処理を行います。明らかに、単体テストには遅延コレクション (プロキシ) はありません。

例:

@Test
public void testGetById() {
    System.out.println("getById");
    TestCompound expResult = new TestCompound(id, "Test Compound", "9999-99-9", null, null, null);

    TestCompoundRepository mockedRepository = mock(TestCompoundRepository.class);
    when(mockedRepository.findOne(id)).thenReturn(expResult);

    ReflectionTestUtils.setField(testCompoundService, "testCompoundRepository",
            mockedRepository, TestCompoundRepository.class);

    TestCompound result = testCompoundService.getById(id);
    assertEquals(expResult, result);
}

万歳、残りは成功します。驚いた!いいえ、そうではありません。

誰かが私が間違っていることを説明できますか? または、そのようなテストのポイントは何ですか?つまり、expResult を返すように指示すると、それが返されます。わお。驚いた!私のサービスではなく、mockitoが機能するかどうかをテストしているように感じます。

編集:

いくつかの愚かなエラーが発生した場合に私が見る唯一の利点は、戻り値を null または同様の愚かなものに設定する不要な行をそこに残すことです。このようなケースは、単体テストによってキャッチされます。それでも「報酬と努力」の比率は悪いように見えますか?

4

6 に答える 6

15

質問は少し古いかもしれませんが、誰かがつまずいた場合に備えて答えを出します.

  • 私はMockitoとJUnitを使用しています。
  • AccountRepository は、JPARepository を拡張した単純な Spring データ リポジトリです。
  • アカウントはプレーンな JPA エンティティです。

サービスをテストして Spring Data リポジトリをモックするには、以下のようなものが必要です。

package foo.bar.service.impl;

import foo.bar.data.entity.Account;
import foo.bar.data.repository.AccountRepository;
import foo.bar.service.AccountService;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class AccountServiceImplTest {

    @Mock
    private static AccountRepository accountRepository;

    @InjectMocks
    private static AccountService accountService = new AccountServiceImpl();

    private Account account;

    @Test
    public void testFindAccount() {

        Integer accountId = new Integer(1);

        account = new Account();
        account.setId(accountId);
        account.setName("Account name");
        account.setCode("Accont code");
        account.setDescription("Account description");

        Mockito.when(accountRepository.findOne(accountId)).thenReturn(account);

        Account retrivedAccount = accountService.findAccount(accountId);

        Assert.assertEquals(account, retrivedAccount);

    }

}
于 2014-09-15T04:23:14.633 に答える
9

Spring Data リポジトリをテストするのが好きな理由の 1 つは、JPA マッピングが正しく定義されていることをテストすることです。私はこれらのテストにモッキング フレームワークを使用しません。実際にコンテナーをブートストラップする Spring テスト フレームワークを使用して、実際のリポジトリーを Junit テストにオートワイヤーして、それに対してテストを実行できるようにします。

リポジトリをモックすることはほとんど役に立たないというあなたの考えに同意します。Spring を使用しているので、Spring Test フレームワークを活用して、リポジトリに対して実際のテストを実行することをお勧めします。これは、H2 などの組み込みデータベースに対して、より単体テストに基づいた方法で実行したり、Oracle や MySql などの実際のデータベース実装に対して実行したりできます。より多くの統合テストを実施します。(開発データベースのコピーに対してこれらを実行します) これらのテストは、JPA マッピングの誤謬や、データベース内の不適切なカスケード設定などの他の項目を明らかにします。

これは、GitHub での私のテストの 1 つの例です。フレームワークが実際にリポジトリをテストにオートワイヤーする方法に注目してください。このリポジトリには、Spring Test フレームワークを構成する方法の例も含まれています。これは、このブログ投稿でも説明しています。

結論として、リポジトリのモックを使用して説明した、リポジトリをテストする利点が得られるとは思えません。

もう 1 つ付け加えておきたいのは、モックは実際のテスト対象クラスでの使用を意図したものではないということです。これらは、テスト対象のクラスに必要な依存関係を提供するために使用されます。

于 2013-03-15T16:25:28.483 に答える
1

あなたはまさにその通りです。単体テストクリアです。そして、それは決して失敗しません(したがって、役に立たない)統合テストで、実際のJPAリポジトリを実際のデータベース(H2たとえばメモリ内)でテストする必要があると思います(私がいつもそうしているように)。

また、サービス (サービスのインターフェース) をテストすることをお勧めします。しばらくしてストレージを (たとえば Mongo に) 変更する場合は、サービス テストを使用して、すべてが以前と同じように機能することを確認できます。

しばらくすると、DB\JPA 関連の問題 (制約、オプティミスティック ロック、遅延読み込み、ID の重複、休止状態の問題など) の多さに驚くことでしょう。

また、実装後にテストを書くだけでなく、テストを介して開発するようにしてください。代わりに、サービスで新しいメソッドを作成する前に-テストを作成し、サービスメソッドを実装してから、実際のアプリケーションで再チェックしてください。少なくとも、サーバーよりもはるかに高速にテストを開始できます。

そのため、多数のテストを作成しないでください。それらがどのように役立つかを見つけてください。

リポジトリにモックを使用することはお勧めできません。サービスが Hibernate\JPA\Database とどのように連携するかをテストします。問題の大部分はの間にあります。

于 2013-03-15T16:54:43.083 に答える