Mockito-스파이 대 모의
Mockito-스파이는 개체에 대한 실제 메서드를 호출하는 반면 모의 개체는 이중 개체에 대한 메서드를 호출한다는 것을 이해합니다. 또한 코드 냄새가 없으면 스파이를 피해야합니다. 그러나 스파이는 어떻게 작동하며 실제로 언제 사용해야합니까? 모의와 어떻게 다릅니 까?
기술적으로 말하면 "모의"와 "스파이"는 특별한 종류의 "테스트 복식"입니다.
Mockito는 불행히도 구별을 이상하게 만듭니다.
mockito의 mock 은 다른 mock 프레임 워크 의 일반 mock 입니다 (호출을 스텁 할 수 있습니다. 즉, 메서드 호출에서 특정 값을 반환 할 수 있습니다).
mockito의 스파이는 다른 모의 프레임 워크 의 부분 모의 입니다 (객체의 일부는 모의 되고 일부는 실제 메서드 호출을 사용합니다).
둘 다 메서드 또는 필드를 모의하는 데 사용할 수 있습니다. 차이점은 모의에서는 완전한 모의 또는 가짜 개체를 만드는 반면 스파이에서는 실제 개체가 있고 특정 방법을 감시하거나 스터 빙하는 것입니다.
물론 스파이 객체에서는 실제 메서드이기 때문에 메서드를 스터 빙하지 않으면 실제 메서드 동작을 호출합니다. 방법을 변경하고 조롱하려면 스텁이 필요합니다.
아래 예를 비교로 고려하십시오.
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.runners.MockitoJUnitRunner;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class MockSpy {
@Mock
private List<String> mockList;
@Spy
private List<String> spyList = new ArrayList();
@Test
public void testMockList() {
//by default, calling the methods of mock object will do nothing
mockList.add("test");
Mockito.verify(mockList).add("test");
assertEquals(0, mockList.size());
assertNull(mockList.get(0));
}
@Test
public void testSpyList() {
//spy object will call the real method when not stub
spyList.add("test");
Mockito.verify(spyList).add("test");
assertEquals(1, spyList.size());
assertEquals("test", spyList.get(0));
}
@Test
public void testMockWithStub() {
//try stubbing a method
String expected = "Mock 100";
when(mockList.get(100)).thenReturn(expected);
assertEquals(expected, mockList.get(100));
}
@Test
public void testSpyWithStub() {
//stubbing a spy method will result the same as the mock object
String expected = "Spy 100";
//take note of using doReturn instead of when
doReturn(expected).when(spyList).get(100);
assertEquals(expected, spyList.get(100));
}
}
모의 또는 스파이를 사용할 때 소리를 지르십니까? 안전하고 외부 서비스 호출을 피하고 장치 내부의 논리를 테스트하려면 mock을 사용하십시오. 외부 서비스를 호출하고 실제 종속성 호출을 수행하거나 단순히 프로그램을 그대로 실행하고 특정 메서드를 스텁하고 싶다면 스파이를 사용하십시오. 이것이 mockito에서 spy와 mock의 차이점입니다.
시작하기에 가장 좋은 곳은 아마도 mockito 문서 일 것입니다 .
일반적으로 mockito mock을 사용하면 스텁을 만들 수 있습니다.
예를 들어 해당 메서드가 비용이 많이 드는 작업을 수행하는 경우 스텁 메서드를 만듭니다. 예를 들어, 데이터베이스 연결을 얻고 데이터베이스에서 값을 검색하여 호출자에게 반환합니다. db 연결을 가져 오는 데 30 초가 걸릴 수 있으므로 컨텍스트 전환 (또는 테스트 실행 중지) 가능성이있는 지점까지 테스트 실행 속도가 느려질 수 있습니다.
테스트중인 로직이 데이터베이스 연결에 관심이 없다면 해당 메서드를 하드 코딩 된 값을 반환하는 스텁으로 대체 할 수 있습니다.
mockito 스파이를 사용하면 메서드가 다른 메서드를 호출하는지 여부를 확인할 수 있습니다. 이것은 레거시 코드를 테스트 할 때 매우 유용 할 수 있습니다.
부작용을 통해 작동하는 방법을 테스트하는 경우 mockito 스파이를 사용하는 것이 유용합니다. 이를 통해 실제 객체에 대한 호출을 위임하고 메서드 호출, 호출 횟수 등을 확인할 수 있습니다.
TL;DR version,
With mock, it creates a bare-bone shell instance for you.
List<String> mockList = Mockito.mock(ArrayList.class);
With spy you can partially mock on an existing instance
List<String> spyList = Mockito.spy(new ArrayList<String>());
Typical use case for Spy: the class has a parameterized constructor, you want to create the object first.
I have created a runable example here https://www.surasint.com/mockito-with-spy/
I copy some of it here.
If you have something like this code:
public void transfer( DepositMoneyService depositMoneyService,
WithdrawMoneyService withdrawMoneyService,
double amount, String fromAccount, String toAccount) {
withdrawMoneyService.withdraw(fromAccount,amount);
depositMoneyService.deposit(toAccount,amount);
}
You may don't need spy because you can just mock DepositMoneyService and WithdrawMoneyService.
But with some legacy code, dependency is in the code like this:
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.
I like the simplicity of this recommendation:
- If you want to be safe and avoid calling external services and just want to test the logic inside of the unit, then use mock.
- If you want to call external service and perform calling of real dependencies, or simply say, you want to run the program as it is and just stub specific methods, then use spy.
Source: https://javapointers.com/tutorial/difference-between-spy-and-mock-in-mockito/
A common difference is:
- If you want to directly stub the method(s) of a dependency, then Mock that dependency.
- If you want to stub the data in a dependency so that all its methods return testing values that you need, then Spy that dependency.
You can follow the below blog url where its compared with below points :
- Object declaration
- When the methods are not mocked
- When the method is mocked
https://onlyfullstack.blogspot.com/2019/02/mockito-mock-vs-spy.html Main tutorial url - https://onlyfullstack.blogspot.com/2019/02/mockito-tutorial.html
참고URL : https://stackoverflow.com/questions/28295625/mockito-spy-vs-mock
'Programing' 카테고리의 다른 글
슬롯에 인수 전달 (0) | 2020.10.28 |
---|---|
MongoDB의 $ in 절이 순서를 보장합니까? (0) | 2020.10.27 |
Postgres 캐시 / 버퍼를보고 지우시겠습니까? (0) | 2020.10.27 |
inspect를 사용하여 Python에서 수신자로부터 호출자 정보를 얻는 방법은 무엇입니까? (0) | 2020.10.27 |
Postgres : 타임 스탬프를 가장 가까운 분으로 올림 또는 내림하는 방법은 무엇입니까? (0) | 2020.10.27 |