IT story

Mockito를 사용할 때 조롱과 스파이의 차이점은 무엇입니까?

hot-time 2020. 7. 5. 07:57
반응형

Mockito를 사용할 때 조롱과 스파이의 차이점은 무엇입니까?


Mockito 스파이의 사용 사례는 무엇입니까?

callRealMethod를 사용하여 모든 스파이 유스 케이스를 모의로 처리 할 수있는 것 같습니다.

내가 볼 수있는 한 가지 차이점은 대부분의 메소드 호출을 실제로 원한다면 모의 대 스파이를 사용하기 위해 일부 코드 줄을 저장합니다. 그것이 더 큰 그림입니까?


답은 설명서에 있습니다 .

실제 부분 모형 (1.8.0부터)

마지막으로 메일 링리스트에 대한 많은 내부 토론과 토론 끝에 Mockito에 부분 모의 지원이 추가되었습니다. 이전에는 코드 냄새로 부분 모의를 고려했습니다. 그러나 부분 모의에 대한 합법적 인 사용 사례를 발견했습니다.

릴리스 1.8 이전 spy ()는 실제 부분 모의를 생성하지 않았으며 일부 사용자에게는 혼란 스러웠습니다. 스파이에 대한 자세한 내용은 here 또는 spy (Object) 메소드에 대한 javadoc을 참조하십시오 .

callRealMethod()는 이후에 소개 spy()되었지만 이전 버전과의 호환성을 보장하기 위해 spy ()가 남아 있습니다.

그렇지 않으면, 당신이 옳습니다 : 스파이의 모든 방법은 스텁되지 않는 한 실제입니다. 모의의 모든 메소드 callRealMethod()는 호출 되지 않는 한 스텁됩니다 . 일반적으로 나는 전통적인 대신 관용구 callRealMethod()를 사용하도록 강요하지 않기 때문에을 선호합니다.doXxx().when()when().thenXxx()


스파이와 모의 차이점

Mockito가 모의 객체를 만들 때 – 실제 인스턴스가 아닌 클래스의 클래스에서 모의 ​​객체를 만듭니다. 이 모의는 단순히 클래스의 베어 셸 인스턴스를 생성하고 클래스와의 상호 작용을 추적하기 위해 완전히 계측되었습니다. 반면에 스파이는 기존 인스턴스를 감 쌉니다. 여전히 일반 인스턴스와 동일한 방식으로 작동합니다. 유일한 차이점은 인스턴스와의 모든 상호 작용을 추적하도록 인스트루먼트됩니다.

다음 예제에서 – ArrayList 클래스의 모형을 만듭니다.

@Test
public void whenCreateMock_thenCreated() {
    List mockedList = Mockito.mock(ArrayList.class);

    mockedList.add("one");
    Mockito.verify(mockedList).add("one");

    assertEquals(0, mockedList.size());
}

보시다시피, 모형 목록에 요소를 추가해도 실제로는 아무것도 추가되지 않으며 다른 부작용없이 메소드를 호출하기 만합니다. 반면에 스파이는 다르게 동작합니다. 실제로 add 메소드의 실제 구현을 호출하고 요소를 기본 목록에 추가합니다.

@Test
public void whenCreateSpy_thenCreate() {
    List spyList = Mockito.spy(new ArrayList());
    spyList.add("one");
    Mockito.verify(spyList).add("one");

    assertEquals(1, spyList.size());
}

size () 메서드를 호출 할 때 크기를 1로 얻지 만이 size () 메서드가 조롱되지 않았기 때문에 객체의 실제 내부 메서드가 호출되었다는 것을 확실히 알 수 있습니다! 그렇다면 1은 어디에서 왔습니까? 내부 실제 size () 메서드는 size ()가 조롱 (또는 스터 빙)되지 않기 때문에 항목이 실제 객체에 추가되었다고 말할 수 있습니다.

출처 : http://www.baeldung.com/mockito-spy + 자기 메모.


8 개의 메소드가있는 오브젝트가 있고 7 개의 실제 메소드를 호출하고 하나의 메소드를 스텁하려는 테스트가있는 경우 두 가지 옵션이 있습니다.

  1. 모의를 사용하면 7 callRealMethod를 호출하고 하나의 메소드를 스텁하여 설정해야합니다.
  2. 를 사용하면 spy하나의 방법을 스텁하여 설정해야합니다.

공식 문서 에 대한 doCallRealMethod부분 모의 객체에 대한 스파이를 사용하는 것이 좋습니다.

부분 모의에 대한 자세한 내용은 javadoc spy (Object)를 참조하십시오. Mockito.spy ()는 부분 모의 객체를 만드는 권장 방법입니다. 그 이유는 spy () 메서드에 전달 된 개체를 생성해야하기 때문에 실제 메서드가 올바르게 구성된 개체에 대해 호출되도록 보장하기 때문입니다.


스파이는 레거시 코드에 대한 단위 테스트를 만들 때 유용 할 수 있습니다 .

https://www.surasint.com/mockito-with-spy/ 여기에서 실행 가능한 예제를 만들었으며 여기에 일부를 복사했습니다.

이 코드와 같은 것이 있다면 :

public void transfer(  DepositMoneyService depositMoneyService, WithdrawMoneyService withdrawMoneyService, 
             double amount, String fromAccount, String toAccount){
    withdrawMoneyService.withdraw(fromAccount,amount);
    depositMoneyService.deposit(toAccount,amount);
}

DepositMoneyService와 WithdrawMoneyService를 조롱 할 수 있기 때문에 스파이가 필요하지 않을 수 있습니다.

그러나 일부 레거시 코드에서 종속성은 다음과 같은 코드에 있습니다.

    public void transfer(String fromAccount, String toAccount, double amount){

        this.depositeMoneyService = new DepositMoneyService();
        this.withdrawMoneyService = new WithdrawMoneyService();

        withdrawMoneyService.withdraw(fromAccount,amount);
        depositeMoneyService.deposit(toAccount,amount);
    }

Yes, you can change to the first code but then API is changed. If this method is being used by many places, you have to change all of them.

Alternative is that you can extract the dependency out like this:

    public void transfer(String fromAccount, String toAccount, double amount){
        this.depositeMoneyService = proxyDepositMoneyServiceCreator();
        this.withdrawMoneyService = proxyWithdrawMoneyServiceCreator();

        withdrawMoneyService.withdraw(fromAccount,amount);
        depositeMoneyService.deposit(toAccount,amount);
    }
    DepositMoneyService proxyDepositMoneyServiceCreator() {
        return new DepositMoneyService();
    }

    WithdrawMoneyService proxyWithdrawMoneyServiceCreator() {
        return new WithdrawMoneyService();
    }

Then you can use the spy the inject the dependency like this:

DepositMoneyService mockDepositMoneyService = mock(DepositMoneyService.class);
        WithdrawMoneyService mockWithdrawMoneyService = mock(WithdrawMoneyService.class);

    TransferMoneyService target = spy(new TransferMoneyService());

    doReturn(mockDepositMoneyService)
            .when(target).proxyDepositMoneyServiceCreator();

    doReturn(mockWithdrawMoneyService)
            .when(target).proxyWithdrawMoneyServiceCreator();

More detail in the link above.

참고URL : https://stackoverflow.com/questions/15052984/what-is-the-difference-between-mocking-and-spying-when-using-mockito

반응형