1前書き


1.1. 概要

この記事では、

モック

について話します。それが何であるか、それを使用する理由、およびJava用の最も使用されているモック・ライブラリーを使用して同じテストケースをモックする方法のいくつかの例を紹介します。

私たちは、モッキング概念のいくつかの正式な/準正式な定義から始めます。次に、テスト中のケースを提示し、各ライブラリの例を使用してフォローアップし、いくつかの結論を出します。選択されたライブラリはhttp://mockito.org/[Mockito]、http://easymock.org/[EasyMock]、およびhttp://jmockit.github.io[JMockit]です。

あなたがすでにモッキングの基本を知っていると感じるなら、多分あなたは次の3つのポイントを読まずにポイント2にスキップすることができます。


1.2. モックを使用する理由

テスト(TDD、ATDD、またはBDD)を中心とした、いくつかの主導的な開発方法論に従ってコードを作成していると仮定します。あるいは単に、その機能を達成するために依存関係に依存する既存のクラスのテストを作成したいということです。

いずれにせよ、クラスを単体テストするときは、その機能のみをテストし、その依存関係はテストしないでください(実装を信頼するか、自分自身でテストするため)。

これを実現するには、テスト対象オブジェクトに、その依存関係を制御できる代替物を提供する必要があります。これにより、極端な戻り値、例外のスロー、または単純に時間のかかるメソッドを固定の戻り値に減らすことができます。

この制御された置き換えは

モック

であり、テストコーディングを単純化しテスト実行時間を短縮するのに役立ちます。


1.3. モックの概念と定義

Martin Fowlerによって書かれたhttp://martinfowler.com/articles/mocksArentStubs.html[article]から、全員がモックについて知っておくべき基本を要約した4つの定義を見てみましょう。


  • ダミー

    オブジェクトは渡されますが、実際には使用されません。通常、

それらは単にパラメータリストを埋めるために使われます。


  • Fake

    オブジェクトには実用的な実装がありますが、通常はいくつかを取ります。

ショートカットは生産には適していません(メモリ内データベースが良い例です)。


  • スタブ

    は通常、テスト中に行われた電話への回答を用意しています。

テスト用にプログラムされたもの以外のものにはまったく応答しません。スタブは、「送信した」メッセージ、または「送信した」メッセージの数だけを記憶する電子メールゲートウェイスタブなど、通話に関する情報も記録できます。


  • モック

    は、ここで話しているものです。事前にプログラムされたオブジェクト

彼らが受けると期待される呼び出しの仕様を形成する期待を持って。


1.4モックするかモックしないか:それが問題です

  • すべてを嘲笑しなければならないわけではありません** 。場合によっては、統合テストを実行した方が良いでしょう。そのメソッドや機能を偽装しても、実際にはほとんど役に立たないからです。私たちのテストケースでは(それは次のポイントで示されるでしょう)それは

    LoginDao

    をテストするでしょう。


LoginDao

は、DBアクセスにサードパーティのライブラリを使用し、それを偽造することは、パラメータが呼び出し用に準備されていることを確認することだけになりますが、呼び出しが必要なデータを返すことをテストする必要があります。

そのため、この例には含まれていません(ただし、サードパーティライブラリの呼び出しに対するモック呼び出しと、サードパーティライブラリの実際のパフォーマンスをテストするためのDBUnitとの統合テストの両方を記述できます)。


2テストケース

前のセクションのすべてを念頭に置いて、非常に典型的なテストケースと、モックを使用してテストする方法を提案しましょう(モックを使用するのが妥当な場合)。これにより、後で別のモックライブラリを比較できるようになるための共通のシナリオを得ることができます。


2.1提案されたケース

提案されているテストケースは、階層化アーキテクチャを持つアプリケーションでのログインプロセスです。

ログイン要求は、DAO(DB上のユーザー資格情報を検索する)を使用するサービスを使用するコントローラーによって処理されます。私たちは各層の実装に深く入り過ぎず、各層の** コンポーネント間の相互作用にもっと焦点を当てます。

このようにして、

LoginController



LoginService

、および

LoginDAO

があります。説明のための図を見てみましょう。


2.2実装

テストケースに使用されている実装について説明しますので、テストで何が起きているのか(または何が起きるのか)を理解することができます。

すべての操作に使用されるモデル

UserForm

から始めましょう。これはユーザーの名前とパスワード(単純化するためにパブリックアクセス修飾子を使用しています)とそのプロパティをモックできるようにするための

username

フィールドの取得メソッドのみを保持します。

public class UserForm {
    public String password;
    public String username;
    public String getUsername(){
        return username;
    }
}


LoginDAO

を使用してみましょう。必要なときにそれらをモックすることができるように、そのメソッドが存在するようにしたいだけなので、機能は無効になります。

public class LoginDao {
    public int login(UserForm userForm){
        return 0;
    }
}


LoginDao

は、その

login

メソッド内で

LoginService

によって使用されます。


LoginService

には、そのモックをテストするために

void

を返す

setCurrentUser

メソッドもあります。

public class LoginService {
    private LoginDao loginDao;
    private String currentUser;

    public boolean login(UserForm userForm) {
        assert null != userForm;
        int loginResults = loginDao.login(userForm);
        switch (loginResults){
            case 1:
                return true;
            default:
                return false;
        }
    }

    public void setCurrentUser(String username) {
        if(null != username){
            this.currentUser = username;
        }
    }
}

最後に、

LoginController

はその

login

メソッドに

LoginService

を使用します。これには以下が含まれます。

  • 偽のサービスへの呼び出しが行われない場合。

  • 1つのメソッドだけが呼び出される場合

  • すべてのメソッドが呼び出されるケース

  • 例外スローがテストされるケース

public class LoginController {
    public LoginService loginService;

    public String login(UserForm userForm){
        if(null == userForm){
            return "ERROR";
        }else{
            boolean logged;

            try {
                logged = loginService.login(userForm);
            } catch (Exception e) {
                return "ERROR";
            }

            if(logged){
                loginService.setCurrentUser(userForm.getUsername());
                return "OK";
            }else{
                return "KO";
            }
        }
    }
}

テストしようとしているのは何なのかを確認したので、次に各ライブラリでモックする方法を見てみましょう。


3テスト設定


3.1 Mockito

Mockitoでは、https://www.javadoc.io/doc/org.mockito/mockito-core/2.8.9[2.8.9]のバージョンを使用します。

モックを作成して使用する最も簡単な方法は

@ Mock



@ InjectMocks

アノテーションを使うことです。最初のものはフィールドを定義するために使用されるクラスのためのモックを作成し、2番目のものはアノテーション付きのモックに前記作成されたモックを注入しようとします。


@ Spy

のように、部分的なモック(非モックメソッドで通常の実装を使用するモック)を作成するためのアノテーションがもっとあります。

とはいえ、この「魔法」のすべてを機能させるために前述のモックを使用するテストを実行する前に、

MockitoAnnotations.initMocks(this)

を呼び出す必要があります。これは通常

@ Before

アノテーション付きメソッドで行われます。


MockitoJUnitRunner

を使用することもできます。

public class LoginControllerTest {

    @Mock
    private LoginDao loginDao;

    @Spy
    @InjectMocks
    private LoginService spiedLoginService;

    @Mock
    private LoginService loginService;

    @InjectMocks
    private LoginController loginController;

    @Before
    public void setUp() {
        loginController = new LoginController();
        MockitoAnnotations.initMocks(this);
    }
}


3.2 EasyMock

EasyMockの場合は、バージョンhttp://mvnrepository.com/artifact/org.easymock/easymock/3.4[3.4](http://easymock.org/api/[Javadoc])を使用します。 EasyMockでは、モックが「機能する」ようにするには、すべてのテストメソッドで

EasyMock.replay(mock)

を呼び出す必要があります。そうしないと、例外が発生します。

モックとテストされたクラスはアノテーションによって定義することもできますが、この場合は、動作する静的メソッドを呼び出す代わりに、テストクラスに

EasyMockRunner

を使用します。

モックは

@ Mock

アノテーションで、テスト対象オブジェクトは

@ TestSubject

1で作成されます(作成されたモックから依存関係が注入されます)。テスト対象オブジェクトはインラインで作成する必要があります。

@RunWith(EasyMockRunner.class)
public class LoginControllerTest {

    @Mock
    private LoginDao loginDao;

    @Mock
    private LoginService loginService;

    @TestSubject
    private LoginController loginController = new LoginController();
}


3.3. JMockit

バージョン1.25はまだリリースされていないので、JMockitではバージョンhttp://jmockit.github.io/changes.html#1.24[1.24](http://jmockit.github.io[Javadoc])を使用します少なくともこれを書いている間)。

JMockitの設定はMockitoと同じくらい簡単ですが、部分的なモックのための特別なアノテーションがなく、実際にはテストランナーとして

JMockit

を使う必要があります。

モックは、

@ Injectable

アノテーション(モックインスタンスを1つだけ作成する)または

@ Mocked

アノテーション(アノテーション付きフィールドのクラスのインスタンスごとにモックを作成する)を使用して定義されます。

テストされたインスタンスは、

@ Tested

アノテーションを使用して作成されます(そして、その疑似依存関係が注入されます)。

@RunWith(JMockit.class)
public class LoginControllerTest {

    @Injectable
    private LoginDao loginDao;

    @Injectable
    private LoginService loginService;

    @Tested
    private LoginController loginController;
}


4モックの呼び出しがないことを確認する


4.1. モッキート

Mockitoでモックが呼び出しを受け取らなかったことを確認するために、モックを受け入れるメソッド

verifyZeroInteractions()

があります。

@Test
public void assertThatNoMethodHasBeenCalled() {
    loginController.login(null);
    Mockito.verifyZeroInteractions(loginService);
}


4.2. EasyMock

モックがコールを受信して​​いないことを確認するには、単に動作を指定しないで、モックを再生し、最後に確認します。

@Test
public void assertThatNoMethodHasBeenCalled() {
    EasyMock.replay(loginService);
    loginController.login(null);
    EasyMock.verify(loginService);
}


4.3. JMockit

モックが電話を受けなかったことを確認するためには、単にそのモックに対する期待を指定せず、そのモックに対して

FullVerifications(モック)

を実行するだけです。

@Test
public void assertThatNoMethodHasBeenCalled() {
    loginController.login(null);
    new FullVerifications(loginService) {};
}


5モックメソッド呼び出しの定義とモックへの呼び出しの確認


5.1. モッキート

  • モックメソッド呼び出し** の場合は、

    Mockito.when(mock.method(args))。thenReturn(value)

    を使用できます。ここでは、単に複数のパラメータとして追加するだけで、複数の呼び出しに対して異なる値を返すことができます:

    thenReturn(value1、value2、value-n、…​)

この構文では、メソッドを返すメソッドを無効にすることはできません。そのような場合は、その方法の検証を使用します(11行目に表示されているとおり)。

モックへの

呼び出しの検証

には

Mockito.verify(mock).method(args)

を使用できます。また、

verifyNoMoreInteractions(mock)

を使用してモックへの呼び出しがもう行われていないことを確認することもできます。

  • 引数の検証** では、特定の値を渡すか、

    any()



    anyString()

    、__anyInt()のような事前定義済みのmatcherを使用できます。以下の例で見るでしょう。

@Test
public void assertTwoMethodsHaveBeenCalled() {
    UserForm userForm = new UserForm();
    userForm.username = "foo";
    Mockito.when(loginService.login(userForm)).thenReturn(true);

    String login = loginController.login(userForm);

    Assert.assertEquals("OK", login);
    Mockito.verify(loginService).login(userForm);
    Mockito.verify(loginService).setCurrentUser("foo");
}

@Test
public void assertOnlyOneMethodHasBeenCalled() {
    UserForm userForm = new UserForm();
    userForm.username = "foo";
    Mockito.when(loginService.login(userForm)).thenReturn(false);

    String login = loginController.login(userForm);

    Assert.assertEquals("KO", login);
    Mockito.verify(loginService).login(userForm);
    Mockito.verifyNoMoreInteractions(loginService);
}


5.2. EasyMock

  • モックメソッド呼び出し** の場合は、

    EasyMock.expect(mock.method(args))。andReturn(value)

    を使用します。

モックへの呼び出しを検証するには、

EasyMock.verify(mock)

を使用できますが、

EasyMock.replay(mock)

を呼び出した後は必ず呼び出してください。

  • 引数を検証** するには、特定の値を渡すか、isA


    _(Class.class)




    anyString()



    anyInt()_

    、およびhttp://easymock.org/user-guideのような事前定義済みのMatcherを使用します。 html#検証 – その種のマッチャーへの期待 – [あなたのマッチャーを定義する可能性]

@Test
public void assertTwoMethodsHaveBeenCalled() {
    UserForm userForm = new UserForm();
    userForm.username = "foo";
    EasyMock.expect(loginService.login(userForm)).andReturn(true);
    loginService.setCurrentUser("foo");
    EasyMock.replay(loginService);

    String login = loginController.login(userForm);

    Assert.assertEquals("OK", login);
    EasyMock.verify(loginService);
}

@Test
public void assertOnlyOneMethodHasBeenCalled() {
    UserForm userForm = new UserForm();
    userForm.username = "foo";
    EasyMock.expect(loginService.login(userForm)).andReturn(false);
    EasyMock.replay(loginService);

    String login = loginController.login(userForm);

    Assert.assertEquals("KO", login);
    EasyMock.verify(loginService);
}


5.3. JMockit

JMockitでは、テスト用にhttp://jmockit.github.io/tutorial/Mocking.html#model[steps]を定義しました。

記録、再生、検証

  • Record

    は新しい

    Expectations()\ {\ {}}

    ブロックで行われ(そこにいくつかのモック用のアクションを定義できます)、

    再生

    は単にテストされたクラスのメソッドを呼び出すことによって行われます。 (検証されたオブジェクト)、そして

    検証** は新しい

    Verifications()\ {\ {}}

    ブロックの中で行われます(そこにいくつかのモックの検証を定義できます)。

  • モックメソッド呼び出し** の場合は、

    mock.method(args)を使用できます。 result = value;

    Expectationsブロック内の

    。ここでは、

    result = value;

    の代わりに

    returns(value1、value2、…​、valuen); __を使用するだけで、複数の呼び出しに対して異なる値を返すことができます。

モックへのhttp://jmockit.github.io/tutorial/Mocking.html#verification[

呼び出しの確認

]については、新しいVerification

__()\ {\ {mock.call(value)}}


または

new Verificationsを使用できます。 (モック)\ {\ {}} __は以前に定義されたすべての期待される呼び出しを検証します。

  • 引数を検証** するには、特定の値を渡すか、

    any



    anyString



    anyLong

    などのhttp://jmockit.github.io/tutorial/Mocking.html#argumentMatching[事前定義された値]などを使用します特別な値と、ここでもあなたのマッチャーを定義する可能性があります(それはハムクレストマッチャーでなければなりません)。

@Test
public void assertTwoMethodsHaveBeenCalled() {
    UserForm userForm = new UserForm();
    userForm.username = "foo";
    new Expectations() {{
        loginService.login(userForm); result = true;
        loginService.setCurrentUser("foo");
    }};

    String login = loginController.login(userForm);

    Assert.assertEquals("OK", login);
    new FullVerifications(loginService) {};
}

@Test
public void assertOnlyOneMethodHasBeenCalled() {
    UserForm userForm = new UserForm();
    userForm.username = "foo";
    new Expectations() {{
        loginService.login(userForm); result = false;
       //no expectation for setCurrentUser
    }};

    String login = loginController.login(userForm);

    Assert.assertEquals("KO", login);
    new FullVerifications(loginService) {};
}


6. モック例外投げ


6.1. モッキート


Mockito.when(mock.method(args))

の後に

.thenThrow(ExceptionClass.class)

を使用すると、例外のスローをモックできます。

@Test
public void mockExceptionThrowin() {
    UserForm userForm = new UserForm();
    Mockito.when(loginService.login(userForm)).thenThrow(IllegalArgumentException.class);

    String login = loginController.login(userForm);

    Assert.assertEquals("ERROR", login);
    Mockito.verify(loginService).login(userForm);
    Mockito.verifyZeroInteractions(loginService);
}


6.2. EasyMock


EasyMock.expect(…​)

呼び出しの後に

.andThrow(new ExceptionClass())

を使用すると、例外のスローをモックできます。

@Test
public void mockExceptionThrowing() {
    UserForm userForm = new UserForm();
    EasyMock.expect(loginService.login(userForm)).andThrow(new IllegalArgumentException());
    EasyMock.replay(loginService);

    String login = loginController.login(userForm);

    Assert.assertEquals("ERROR", login);
    EasyMock.verify(loginService);
}


6.3. JMockit

JMockitoを使った例外のモック投げは特に簡単です。 「通常の」戻り値ではなく、モックされたメソッド呼び出しの結果として例外を返すだけです。

@Test
public void mockExceptionThrowing() {
    UserForm userForm = new UserForm();
    new Expectations() {{
        loginService.login(userForm); result = new IllegalArgumentException();
       //no expectation for setCurrentUser
    }};

    String login = loginController.login(userForm);

    Assert.assertEquals("ERROR", login);
    new FullVerifications(loginService) {};
}


7. 周りを通過するようにオブジェクトをモックする


7.1. モッキート

また、メソッド呼び出しの引数として渡すためのモックを作成することもできます。

Mockitoを使えば、ワンライナーでそれができます。

@Test
public void mockAnObjectToPassAround() {
    UserForm userForm = Mockito.when(Mockito.mock(UserForm.class).getUsername())
      .thenReturn("foo").getMock();
    Mockito.when(loginService.login(userForm)).thenReturn(true);

    String login = loginController.login(userForm);

    Assert.assertEquals("OK", login);
    Mockito.verify(loginService).login(userForm);
    Mockito.verify(loginService).setCurrentUser("foo");
}


7.2. EasyMock

モックは

EasyMock.mock(Class.class)

とインラインで作成できます。

その後、

EasyMock.expect(mock.method())

を使用して実行の準備をすることができます。使用する前には必ず

EasyMock.replay(mock)

を呼び出してください。

@Test
public void mockAnObjectToPassAround() {
    UserForm userForm = EasyMock.mock(UserForm.class);
    EasyMock.expect(userForm.getUsername()).andReturn("foo");
    EasyMock.expect(loginService.login(userForm)).andReturn(true);
    loginService.setCurrentUser("foo");
    EasyMock.replay(userForm);
    EasyMock.replay(loginService);

    String login = loginController.login(userForm);

    Assert.assertEquals("OK", login);
    EasyMock.verify(userForm);
    EasyMock.verify(loginService);
}


7.3. JMockit

1つのメソッドだけでモックを作成するには、モックされたオブジェクトをテストメソッドに渡すだけです。そうすれば、他のモックと同じように期待を生み出すことができます。

@Test
public void mockAnObjectToPassAround(@Mocked UserForm userForm) {
    new Expectations() {{
        userForm.getUsername(); result = "foo";
        loginService.login(userForm); result = true;
        loginService.setCurrentUser("foo");
    }};

    String login = loginController.login(userForm);

    Assert.assertEquals("OK", login);
    new FullVerifications(loginService) {};
    new FullVerifications(userForm) {};
}


8カスタム引数のマッチング


8.1. モッキート

モックされた呼び出しの引数マッチングは、固定値や

anyString()

よりも少し複雑にする必要がある場合があります。そのような場合、Mockitoでは

argThat(ArgumentMatcher <>)

と共に使用されるmatcherクラスがあります。

@Test
public void argumentMatching() {
    UserForm userForm = new UserForm();
    userForm.username = "foo";
   //default matcher
    Mockito.when(loginService.login(Mockito.any(UserForm.class))).thenReturn(true);

    String login = loginController.login(userForm);

    Assert.assertEquals("OK", login);
    Mockito.verify(loginService).login(userForm);
   //complex matcher
    Mockito.verify(loginService).setCurrentUser(ArgumentMatchers.argThat(
        new ArgumentMatcher<String>() {
            @Override
            public boolean matches(String argument) {
                return argument.startsWith("foo");
            }
        }
    ));
}


8.2. EasyMock

EasyMockでは、実際のマッチャーを作成してから

EasyMock.reportMatcher(IArgumentMatcher)

を使用してそれを報告する静的メソッドを作成する必要があるため、カスタム引数のマッチングは少し複雑です。

このメソッドが作成されたら、メソッドの呼び出しであなたのモックの期待にそれを使用します(例の行に見られるように)。

@Test
public void argumentMatching() {
    UserForm userForm = new UserForm();
    userForm.username = "foo";
   //default matcher
    EasyMock.expect(loginService.login(EasyMock.isA(UserForm.class))).andReturn(true);
   //complex matcher
    loginService.setCurrentUser(specificArgumentMatching("foo"));
    EasyMock.replay(loginService);

    String login = loginController.login(userForm);

    Assert.assertEquals("OK", login);
    EasyMock.verify(loginService);
}

private static String specificArgumentMatching(String expected) {
    EasyMock.reportMatcher(new IArgumentMatcher() {
        @Override
        public boolean matches(Object argument) {
            return argument instanceof String
              && ((String) argument).startsWith(expected);
        }

        @Override
        public void appendTo(StringBuffer buffer) {
           //NOOP
        }
    });
    return null;
}


8.3. JMockit

JMockitとのカスタム引数マッチングは、特別な

withArgThat(Matcher)

メソッド(http://hamcrest.org/[Hamcrest]`s

Matcher

オブジェクトを受け取る)を使って行われます。

@Test
public void argumentMatching() {
    UserForm userForm = new UserForm();
    userForm.username = "foo";
   //default matcher
    new Expectations() {{
        loginService.login((UserForm) any);
        result = true;
       //complex matcher
        loginService.setCurrentUser(withArgThat(new BaseMatcher<String>() {
            @Override
            public boolean matches(Object item) {
                return item instanceof String && ((String) item).startsWith("foo");
            }

            @Override
            public void describeTo(Description description) {
               //NOOP
            }
        }));
    }};

    String login = loginController.login(userForm);

    Assert.assertEquals("OK", login);
    new FullVerifications(loginService) {};
}


9部分モッキング


9.1. モッキート

Mockitoでは、2つの方法で部分モック(一部のメソッドでモックメソッド呼び出しの代わりに実際の実装を使用するモック)を使用できます。

通常のモックメソッドの呼び出し定義で

.thenCallRealMethod()

を使用することも、モックの代わりに

spy

を作成することもできます。メソッド

@Test
public void partialMocking() {
   //use partial mock
    loginController.loginService = spiedLoginService;
    UserForm userForm = new UserForm();
    userForm.username = "foo";
   //let service's login use implementation so let's mock DAO call
    Mockito.when(loginDao.login(userForm)).thenReturn(1);

    String login = loginController.login(userForm);

    Assert.assertEquals("OK", login);
   //verify mocked call
    Mockito.verify(spiedLoginService).setCurrentUser("foo");
}


9.2. EasyMock

EasyMockでは、モックを作成するときにどのメソッドをモックするかを定義する必要があるため、部分モックも少し複雑になります。

これは

EasyMock.partialMockBuilder(Class.class).addMockedMethod(“ methodName”)。createMock()

で行われます。

これが完了したら、モックを他の部分的でないモックのように使用できます。

@Test
public void partialMocking() {
    UserForm userForm = new UserForm();
    userForm.username = "foo";
   //use partial mock
    LoginService loginServicePartial = EasyMock.partialMockBuilder(LoginService.class)
      .addMockedMethod("setCurrentUser").createMock();
    loginServicePartial.setCurrentUser("foo");
   //let service's login use implementation so let's mock DAO call
    EasyMock.expect(loginDao.login(userForm)).andReturn(1);

    loginServicePartial.setLoginDao(loginDao);
    loginController.loginService = loginServicePartial;

    EasyMock.replay(loginDao);
    EasyMock.replay(loginServicePartial);

    String login = loginController.login(userForm);

    Assert.assertEquals("OK", login);
   //verify mocked call
    EasyMock.verify(loginServicePartial);
    EasyMock.verify(loginDao);
}


9.3. JMockit

JMockitによる部分モックは特に簡単です。疑似動作が__Expectations()\ {\ {}}で定義されていないすべてのメソッド呼び出しは、「実際の」実装を使用します。

この場合、

LoginService.login(UserForm)

には何の期待も与えられていないので、実際の実装(および

LoginDAO.login(UserForm)

の呼び出し)が実行されます。

@Test
public void partialMocking() {
   //use partial mock
    LoginService partialLoginService = new LoginService();
    partialLoginService.setLoginDao(loginDao);
    loginController.loginService = partialLoginService;

    UserForm userForm = new UserForm();
    userForm.username = "foo";
   //let service's login use implementation so let's mock DAO call
    new Expectations() {{
        loginDao.login(userForm); result = 1;
       //no expectation for loginService.login
        partialLoginService.setCurrentUser("foo");
    }};

    String login = loginController.login(userForm);

    Assert.assertEquals("OK", login);
   //verify mocked call
    new FullVerifications(partialLoginService) {};
    new FullVerifications(loginDao) {};
}


10結論

この記事では、3つのJavaモック・ライブラリーを比較しました。それぞれのライブラリーには、それぞれ長所と短所があります。

  • それらの3つすべては、あなたを助けるために注釈で

    簡単に設定

    されています

モックインジェクションを可能な限り痛みのないものにするためのランナーで、モックとテスト対象オブジェクトを定義します。

  • ** Mockitoには特別な注釈があるので、ここで勝つと思います。

部分的なモックですが、JMockitはそれを必要とさえしないので、それはそれらの2つの間の結びつきであると言いましょう。

  • それらの3つすべては、多かれ少なかれ** record-replay-verifyに従っています

pattern ** が、私たちの意見では、そうするのが一番良いのはJMockitです。JMockitはそれらをブロックで使用することを強いるので、テストはより構造化されます。


  • 使いやすさ

    は重要ですので、できる限り少なく作業できます

テストを定義してください。 JMockitは、常に固定された同じ構造のための選択されたオプションになります。

  • Mockitoは多かれ少なかれ最も知られているので、

    コミュニティ

より大きい。

  • モックを使いたいときに毎回

    replay

    を呼ばなければならないのは明らかです。

  • no-go ** なので、EasyMockにはマイナス1を付けます。


  • 一貫性/単純さ

    も私にとって重要です。私達は方法を愛した

JMockitの結果を返すのは、「通常の」結果の場合も例外の場合も同じです。

これまで述べてきましたが、これまではシンプルさと固定された構造に魅了されてきたのでMockitoを使用してきましたが、JMockitを勝者の一種として選択するつもりです。今後使用してください。

このチュートリアルの

完全な実装

はhttps://github.com/eugenp/tutorials/tree/master/testing-modules/mocks[GitHubプロジェクト]にありますので、それをダウンロードして試してみてください。