O espião pode ser útil quando você deseja criar testes de unidade para código legado .
Criei um exemplo executável aqui https://www.surasint.com/mockito-with-spy/ , copio alguns deles aqui.
Se você tiver algo parecido com este código:
public void transfer( DepositMoneyService depositMoneyService, WithdrawMoneyService withdrawMoneyService,
double amount, String fromAccount, String toAccount){
withdrawMoneyService.withdraw(fromAccount,amount);
depositMoneyService.deposit(toAccount,amount);
}
Você pode não precisar de espionagem, porque pode apenas zombar de DepositMoneyService e WithdrawMoneyService.
Mas com alguns códigos herdados, a dependência está no código assim:
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);
}
Sim, você pode alterar para o primeiro código, mas a API é alterada. Se esse método estiver sendo usado por muitos lugares, você precisará alterar todos eles.
Alternativa é que você pode extrair a dependência assim:
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();
}
Então você pode usar o espião e injetar a dependência assim:
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();
Mais detalhes no link acima.