La spia può essere utile quando si desidera creare unit test per il codice legacy .
Ho creato un esempio eseguibile qui https://www.surasint.com/mockito-with-spy/ , ne copio alcuni qui.
Se hai qualcosa come questo codice:
public void transfer( DepositMoneyService depositMoneyService, WithdrawMoneyService withdrawMoneyService,
double amount, String fromAccount, String toAccount){
withdrawMoneyService.withdraw(fromAccount,amount);
depositMoneyService.deposit(toAccount,amount);
}
Potresti non aver bisogno di spia perché puoi semplicemente deridere DepositMoneyService e WithdrawMoneyService.
Ma con alcuni codici legacy, la dipendenza è nel codice in questo modo:
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);
}
Sì, è possibile passare al primo codice ma poi l'API viene modificata. Se questo metodo viene utilizzato da molti luoghi, è necessario modificarli tutti.
L'alternativa è che puoi estrarre la dipendenza in questo modo:
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();
}
Quindi puoi usare la spia per iniettare la dipendenza in questo modo:
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();
Maggiori dettagli nel link sopra.