Suggerisco di rifarlo.
Le informazioni che ho guardato è suggerendo che il desiderio di testare quelli metodi privati potrebbe essere un odore di codice. Alcune persone suggeriscono che potrebbe essere un segno che questo dovrebbe essere refactored in una classe separata e reso pubblico.
Hai coperto le varie ragioni a favore e contro di esso nella tua stessa domanda, sembri essere ben consapevole degli argomenti. Ma hai un metodo che sembra piuttosto complicato e implica un'API esterna. Vale la pena provare da solo.removeInvalidOperations()
può ancora essere un metodo privato sulla classe in cui si trova, ma sostanzialmente delegherebbe a un'altra dipendenza.
class YourClass
{
private OperationRemover remover;
public void addKeywords() {
// whatever
removeInvalidOperations();
}
private void removeInvalidOperations() {
remover.remove();
}
}
Questo ti dà il vantaggio di essere in grado di sostituire questa dipendenza ad un certo punto, tra cui essere in grado di testare il metodo di addKeywords()
senza realmente effettuare una chiamata API esterna, il che renderebbe il test che il metodo più semplice.OperationRemover
potrebbe essere un'interfaccia, ad esempio, e per scopi di test, si passa semplicemente uno stub al suo posto invece della versione concreta utilizzata nella produzione. Per quanto riguarda la versione concreta, è possibile scrivere test indipendentemente da ciò che sta accadendo con la classe esistente.
Io in realtà non vedo perché ho un problema con il mio codice di progettazione corrente, ma anche non mi piace l'idea di modificare il mio codice di produzione per soddisfare le mie esigenze test.
La facilità di testabilità è un vantaggio secondario. Guardalo in un altro modo: quello che stai facendo in realtà è rendere il codice liberamente accoppiato ed estensibile. In alto, abbiamo separato la chiamata all'API esterna dal codice che potrebbe essere necessario utilizzare il risultato. L'API esterna potrebbe cambiare. Potresti passare da un servizio all'altro, ma il codice che utilizza il risultato non deve preoccuparsi. Quella classe può rimanere la stessa, solo la classe che effettivamente pone le chiamate deve essere modificata (o sostituita).
Esempio di mondo reale: l'anno è il 2007 e si lavora per una banca in un grande centro finanziario negli Stati Uniti. La tua applicazione deve utilizzare le informazioni dell'account. Il tuo codice raggiunge un servizio web di qualche tipo all'interno della banca e ottiene le informazioni di cui ha bisogno, nella forma di cui ha bisogno, quindi procede al suo trattamento. Nel 2008, il settore finanziario statunitense implode e la tua banca (che è sull'orlo del collasso) viene divorata da un'altra banca. La tua applicazione è stata risparmiata, ma ora devi raggiungere una diversa API già esistente nella banca sopravvissuta per ottenere informazioni sull'account da lì. Il codice che consuma queste informazioni sull'account deve cambiare? Non necessariamente. Sono le stesse informazioni sull'account di prima, solo da una fonte diversa. No, tutto ciò che deve essere modificato è l'implementazione che richiama le API. Il codice del consumo non deve mai sapere.
Il fatto che un accoppiamento così libero promuova e faciliti i test è un vantaggio.
Una soluzione rapida che ho spesso utilizzato è quella di modificare l'accesso da privato a predefinito (pacchetto) e commentare l'accesso al pacchetto // // solo per i test di unità. Se questo è accettabile dipende dagli standard di codifica e da quanto ci si fida i tuoi colleghi programmatori per capire che questo metodo, anche se l'accesso al pacchetto, non è una "vera API". – user949300