Nell'azienda in cui lavoro, abbiamo molte classi di "utilità", ognuna con un sacco di codice all'interno (migliaia di righe) e sono tutte statiche. E un metodo statico chiama anothers. Il problema qui è che quando si vogliono testare altre classi si ha un sacco di dolore quando la funzione testata usa queste classi di utilità statiche all'interno perché non è possibile sovrascriverle (poiché sono statiche). Usiamo il mockito per i test. Powermock non è un'opzione perché a volte rompe bytecode ed è molto più lento di mockito.
Ciò che abbiamo deciso - è di trasferirli tutti in singleton, passo dopo passo, così durante il test possiamo prendere in giro l'istanza di singleton e il metodo di test che vogliamo (o anche testare qualche metodo di utilità perché devono anche essere coperti dagli autotest). È semplice farlo per le classi piccole, ma nel nostro caso ci sono 6006 linee di classe, 1261 linee di classe, 2231 linee di classe e così via. Convertirli tutti in singleton manualmente è molto doloroso, quindi c'è un modo per farlo automaticamente? O forse almeno qualche aiutante.
Esempio di codice non testabile:
static Object methodA()
{
*very heavy code here*
}
static void methodB()
{
*some code*
xx = methodA();
*here is code I've changed and want to test*
*some code*
}
Immaginiamo di aver cambiato qualcosa in methodB e di voler testare la mia modifica. Quindi non voglio che questo metodo venga chiamato in quanto non correlato al test. Ma non posso cambiare il metodo con Mockito in questo caso. Tuttavia è possibile se all'interno del metodoA c'è una chiamata allo stesso metodo Singleton che può essere deriso perché non è statico.
Quindi se lo converti in qualcosa di simile
public class A {
private A(){}
public Object methodAInner()
{
*heavy code here*
}
public void methodBInner()
{
*some code*
xx = methodA();
*here is code I've changed and want to test*
*some code*
}
private static A getInstance()
{
return SpringUtils.getBean(A.class); // here can be anything that supports testing
}
static Object methodA()
{
return getInstance().methodAInner();
}
static void methodB()
{
getInstance().methodBInner();
}
}
Puoi fare in modo che questi SpringUtil restituiscano l'oggetto mocked con il metodo reale B e non apportino quasi nessuna modifica al codice esistente (utile per git blame), rimuovi solo i modificatori statici ei nomi dei metodi di chnge. Una cosa è la più importante per l'eredità: consente di non modificare il codice che utilizza questa classe di utilità.