2017-01-10 2 views
1

다음은 WorkWithArrayList의 예제 클래스를 볼 수 있습니다. 이 클래스에는 removeFirstThreeinsertData의 두 가지 메소드가 있습니다. removeFirstThree 메서드는 List을 인수로 가져 와서 수정하고 데이터베이스에 삽입합니다. for 루프에서는 List의 첫 번째 요소 인 Integer을 제거한 것처럼이 수정을 보여주고 모든 반복에 데이터를 삽입합니다.Mockito에 의해 예상 인수 (java.util.List를 인수로)가 호출되었는지 확인하는 방법

깨닫고 싶은 건 insertData 메서드의 인수를 확인하는 것입니다. 하지만 verify 첫 번째 방법은 verify(workWithArrayList).insertData(expected); 선언으로만 확인합니다.

package test; 

import org.junit.Before; 
import org.junit.Test; 

import java.util.ArrayList; 
import java.util.List; 

import static org.mockito.Mockito.spy; 
import static org.mockito.Mockito.verify; 

public class MockitoVerifyWithArrayListTest { 

    private WorkWithArrayList workWithArrayList; 
    private List<Integer> actual; 
    private List<Integer> expected; 

    @Before 
    public void setUp() throws Exception { 

     workWithArrayList = spy(new WorkWithArrayList()); 

     actual = new ArrayList<>(); 
     actual.add(1); 
     actual.add(2); 
     actual.add(3); 
     actual.add(4); 
     actual.add(5); 
     actual.add(6); 

     expected = new ArrayList<>(); 
     expected.add(1); 
     expected.add(2); 
     expected.add(3); 
     expected.add(4); 
     expected.add(5); 
     expected.add(6); 
    } 

    @Test 
    public void test() throws Exception { 

     workWithArrayList.removeFirstThree(actual); 

     expected.remove(0); 
     verify(workWithArrayList).insertData(expected); 

     expected.remove(0); 
     verify(workWithArrayList).insertData(expected); 

     expected.remove(0); 
     verify(workWithArrayList).insertData(expected); 
    } 

    public class WorkWithArrayList { 

     public void removeFirstThree(List<Integer> integers) { 

      for (int i = 0; i < 3; i++) { 

       integers.remove(0); 
       insertData(integers); 
      } 
     } 

     public void insertData(List<Integer> integers) { 

     } 
    } 
} 

나는 다음과 같은 오류에 직면하고이 테스트를 실행하면 :

Argument(s) are different! Wanted: 
workWithArrayList.insertData(
    [2, 3, 4, 5, 6] 
); 
-> at test.MockitoVerifyWithArrayListTest.test(MockitoVerifyWithArrayListTest.java:46) 
Actual invocation has different arguments: 
workWithArrayList.insertData(
    [4, 5, 6] 
); 
-> at test.MockitoVerifyWithArrayListTest.test(MockitoVerifyWithArrayListTest.java:43) 

편집 : 우리가 Mockito.verify 방법의 javadoc에 보면, 우리는이를 볼 수 있습니다 통과
인수됩니다 비교 방법은 equals()입니다.

하지만 변수 actualexpected은 동일하며 둘 다 첫 번째 요소를 제거하더라도 동일하게 유지됩니다. 왜이 테스트가 실패하는지 나는 흥미 롭다.

답변

1

Mockito는 호출 세부 정보를 저장할 때 개체를 복제하거나 복사하지 않으며 모든 종류의 "스냅 샷"을 가져옵니다. 값이 전달되고 Mockito가 참조를 복사합니다. 즉, 실제의 변경 가능한 객체와 일치시키는 것은 매우 직관적 일 수 있습니다.

@Test 
public void test() throws Exception { 
    // expected: [1, 2, 3, 4, 5, 6]; actual: [1, 2, 3, 4, 5, 6]; 

    workWithArrayList.removeFirstThree(actual); 

    // expected: [1, 2, 3, 4, 5, 6]; actual: [4, 5, 6] 
    // Mockito's invocation list: 
    // three calls to removeFirstThree(actual), where actual is [4, 5, 6], 
    // even though actual had different values during each of the calls! 

    expected.remove(0); 
    verify(workWithArrayList).insertData(expected); 

    expected.remove(0); 
    verify(workWithArrayList).insertData(expected); 

    expected.remove(0); 
    verify(workWithArrayList).insertData(expected); 
} 

는이 때문에 가변 데이터, 데이터를 복사 (가 발생하기 또는 다른 통화의 각을 감지)를 Answer에 의존하지 않고 정확한 동작을 보여주기 위해 Mockito를 사용하는 것은 매우 어려울 수 있습니다.

2

내가 정말로 중요한 것을 놓치지 않는 한, 당신은 물건을 섞어서 물건을 시험하기가 더 힘들어집니다.

당신은 참조 어딘가에 목록이 다른 책임입니다 퍼팅 목록과 을 수정. 그러므로 두 가지 요소를 같은 클래스에 강제 적용하면 테스트가 힘들어집니다!

더 나은 접근 방법은 다음과 같습니다. 목록 조작을 수행하는 클래스를 작성하십시오. 이 클래스는 조롱없이 테스트 할 수 있습니다! 목록을 만듭니다. 그 클래스에 수정 클래스를 지정하십시오; 돌아 오는 것을 확인하십시오. 그냥 필수라고 주장!

그리고 목록 조작이 효과가 있다는 것을 알게되면 DB 작업 목록을 작성하는 것만 테스트하면됩니다. 그리고 쓰는 목록이 실제로 어떻게 보이는지 상관하지 않습니다!

관련 문제