Mockitoテストの基本的な使い方

20321 ワード

一、mockテストとは何ですか。mockオブジェクトとは何ですか。


まず、次の例を見てみましょう.
上の図からAをテストする場合は、まず依存ツリー全体、すなわちBCDEの例を構築する必要があることがわかります.
代替案はmocksを使うことです
図からはっきり見える
mockオブジェクトは、デバッグ中に実際のオブジェクトとして使用される代替品です.mockテストとは、テスト中に構築しにくいオブジェクトに対してテストの代わりに仮想オブジェクトを使用する方法をmockテストと呼びます.
mockテストとは何かを知ったら、mockフレームワーク-Mockitoを認識しましょう.

二、Mockitoとは


覚えやすい名前のほか、Mockitoは異なる方法でmockingテストを試み、EasyMockの代わりに簡単な軽量級のフレームワークである.簡単で、テストコードの可読性が高く、豊富なドキュメントがjavadocに含まれており、IDEで直接ドキュメント、インスタンス、説明を表示できます.詳細:http://code.google.com/p/mockito/

三、StubとMock


同じ点:StubオブジェクトとMockオブジェクトは外部依存をシミュレートするために使用され、制御できます.
異なる点:-stubは完全に外部依存をシミュレートし、テストに必要なテストデータを提供します.-mockオブジェクトは、テストが合格できるかどうかを判断するために使用されます.すなわち、テスト中の依存オブジェクト間のインタラクションが予想されるかどうかを検証するために使用されます.-mockingフレームワークでは、stubとmockの両方としてmockオブジェクトを同時に使用できますが、厳密な違いはありません.
詳細:http://martinfowler.com/articles/mocksArentStubs.html

四、mockito入門例

  • Maven依存:
  • <dependency>
      <groupId>org.mockitogroupId>
        <artifactId>mockito-allartifactId>
        <version>1.10.19version>
    dependency>
  • 基本用法
  •     @Test
        @SuppressWarnings("unchecked")
        public void testSimple() throws Exception {
            // mock 
            /* mock final,Anonymous ,primitive mock。*/
            List<String> list = mock(List.class);
    
            // 
            when(list.get(0)).thenReturn("hello world!");
            //doReturn("hello wolrd!").when(list).get(0);
    
            // 
            when(list.get(1)).thenThrow(new RuntimeException("exception!"));
    
            // void ( , donothing, dothrow runtime )
            doNothing().doThrow(new RuntimeException("void exception")).when(list).clear();
            list.clear();
            list.clear();
            verify(list, times(2)).clear();
    
            String result = list.get(0);
    
            // 
            verify(list).get(0);
    
            //junit 
            Assert.assertEquals("hello world!", result);
    
        }

    Ps:mockオブジェクトを作成するにはfinal,Anonymous,primitiveクラスはmockできません.

    五、パラメータ整合器(Argument Matcher)


    Matchersクラスにはパラメータマッチング器anyInt、anyString、anyMapがたくさんあります.MockitoクラスはMatchersに継承され、Stubbingでは組み込みパラメータマッチングを使用します.次の例です.
       /**
         *  
         *  , , stubbing verify 。
         */
        @Test
        @SuppressWarnings("unchecked")
        public void argumentMatcherTest() throws Exception {
    
            List<String> list = mock(List.class);
            when(list.get(anyInt())).thenReturn("hello", "world", "hqq");
            String result = list.get(0) + list.get(1);
            verify(list, times(2)).get(anyInt());
            Assert.assertEquals("helloworld", result);
    
            Map<Integer, String> map = mock(Map.class);
            when(map.put(anyInt(), anyString())).thenReturn("hello");
            String str = map.put(1, "world");
            verify(map).put(eq(1), eq("world"));
            Assert.assertEquals("hello", str);
        }

    パラメータマッチングを使用する場合は、stubbingでもverifyでも、すべてのパラメータはパラメータマッチングを使用します.

    六、メソッド呼び出しの検証(具体的な呼び出し回数、少なくとも一回、一度もない)

       /**
         *  
         */
        @Test
        public void verifyInvocate() throws Exception {
            List<String> list = mock(List.class);
    
            list.add("one");
            list.add("twice");
            list.add("twice");
            list.add("three times");
            list.add("three times");
            list.add("three times");
    
            verify(list, times(1)).add("one");
            verify(list, times(2)).add("twice");
            verify(list, times(3)).add("three times");
            verify(list, times(0)).add("never added");
    
            verify(list, atLeastOnce()).add("one");
            verify(list, atLeast(2)).add("twice");
            verify(list, atMost(3)).add("three times");
        }

    七、順番に検証する

        /**
         *  
         */
        @Test
        @SuppressWarnings("unchecked")
        public void orderTest() throws Exception {
            // A.  mock 。
            List singleMock = mock(List.class);
            singleMock.add("first");
            singleMock.add("second");
            // Mock InOrder 
            InOrder inOrderSingle = inOrder(singleMock);
            // 
            inOrderSingle.verify(singleMock).add("first");
            inOrderSingle.verify(singleMock).add("second");
    
            // B.  mock 
            List firstMock = mock(List.class);
            List secondMock = mock(List.class);
    
            firstMock.add("first add");
            secondMock.add("second add");
    
            InOrder inOrderMulti = inOrder(firstMock, secondMock);
    
            inOrderMulti.verify(firstMock).add("first add");
            inOrderMulti.verify(secondMock).add("second add");
        }

    八、インタラクティブ操作がMockオブジェクト上で実行されていないことを確認する

    // mock —— mockOne 
    mockOne.add("one");
    
    // 
    verify(mockOne).add("one");
    
    // 
    verify(mockOne, never()).add("two");
    
    // Mock 
    verifyZeroInteractions(mockTwo, mockThree);

    九、余分な呼び出しを探す

    // mock
    mockedList.add("one");
    mockedList.add("two");
    
    verify(mockedList).add("one");
    
    // 
    verifyNoMoreInteractions(mockedList);

    十、素早くmockオブジェクトを作成する——@Mock注記

    @RunWith(MockitoJUnitRunner.class)
    public class AnnotationMockTest {
    
        @Mock
        List list;
    
        @Mock
        private User user;
    
        @Test
        public void test() throws Exception {
            when(list.get(0)).thenReturn("hello,mockito");
            System.out.println(list.get(0));
        }
    
        @Test
        public void userTest() throws Exception {
            when(user.getName()).thenReturn("heqianqian");
            System.out.println(user.getName());
        }
    }

    十一、反復式のテスト


    同じメソッドで呼び出された戻り値または異常のテスト杭が必要になる場合があります.典型的な運用はMock反復器の使用である.Mockitoの初期バージョンにはこの特性はありません.たとえば、開発者は反復器の代わりにIterableまたは簡単な集合を使用する場合があります.これらの方法は、テスト杭としてより自然な方法を提供し、いくつかのシーンでは、連続的な呼び出しのためにテスト杭として役立ちます.たとえば、次のようにします.
    @RunWith(MockitoJUnitRunner.class)
    public class IteratorMockitoTest {
    
        @Mock
        List list;
    
        @Test
        public void iteratorTest() throws Exception {
            when(list.get(0)).thenReturn("one","two","three");
            // one
            System.out.println(list.get(0));
            // two
            System.out.println(list.get(0));
            // three
            System.out.println(list.get(0));
            System.out.println(list.get(0));
        }
    }
    

    十二、コールバックのために試験杭を作る


    汎用インタフェースAnswerに杭を打つ.
    public class CallbackMockitoTest {
    
        @Test
        @SuppressWarnings("unchecked")
        public void callbackTest() throws Exception {
            List list = mock(List.class);
            list.add("hello");
            when(list.get(0)).thenAnswer(new Answer() {
                @Override
                public String answer(InvocationOnMock invocationOnMock) throws Throwable {
                    // 
                    Object[] args = invocationOnMock.getArguments();
                    // Mock 
                    Object mock = invocationOnMock.getMock();
                    return "called with arguments:" + args[0].toString();
                }
            });
    
            System.out.println(list.get(0));
    
        }
    }
    

    十三、真実の対象を監視する


    実際のオブジェクトに対してモニタリング(spy)オブジェクトを作成できます.このspyオブジェクトを使用すると、この関数が杭打ちされない限り、実際の方法も呼び出されます.実際には、残されたコードを処理する場合など、節制されたspyオブジェクトが必要です.
      List list = new LinkedList();
    List spy = spy(list);
    
     // :
     when(spy.size()).thenReturn(100);
    
     // spy :
     spy.add("one");
     spy.add("two");
    
     // list 
     System.out.println(spy.get(0));
    
     // size() , 100
     System.out.println(spy.size());
    
     // 
     verify(spy).add("one");
     verify(spy).add("two");

    モニタリング対象にwhen(Object)を用いて杭打ちを行うことは不可能または非現実的である場合がある.そこでspyを使うときはdoReturn|Answer|Throw()という一連の方法を考えて杭打ちをしてください.例:
     List list = new LinkedList();
     List spy = spy(list);
    
     // : spy.get(0) get(0) , IndexOutOfBoundsException, list 。
     when(spy.get(0)).thenReturn("foo");
    
     // doReturn 。
     doReturn("foo").when(spy).get(0);
  • Mockitoは、実際のオブジェクトエージェント関数には呼び出されません.実際には、実際のオブジェクトがコピーされます.したがって、実際のオブジェクトを保持して対話する場合は、モニタリングオブジェクトから正しい結果を期待しないでください.モニタリングオブジェクトで杭打ちされていない関数を呼び出すと、実際のオブジェクトの対応する関数は呼び出されません.そのため、実際のオブジェクトには結果は表示されません.
  • そのため、実際のオブジェクトを監視している間に、この実際のオブジェクトの関数のテスト杭を作りたいと思っています.それは自分で面倒を見ています.これらの関数を検証するべきではありません