Come faccio ad iniettare oggetti test quando gli oggetti reali sono creati dinamicamente?

8

Voglio rendere una classe testabile usando l'iniezione di dipendenza. Ma la classe crea più oggetti in fase di esecuzione e passa valori diversi al loro costruttore. Ecco un esempio semplificato:

public abstract class Validator {
    private ErrorList errors;

    public abstract void validate();

    public void addError(String text) {
        errors.add(
            new ValidationError(text));
    }

    public int getNumErrors() {
        return errors.count()
    }
}

public class AgeValidator extends Validator {
    public void validate() {
        addError("first name invalid");
        addError("last name invalid");
    }
}

(Esistono molte altre sottoclassi di Validator.)

Qual è il modo migliore per cambiare questo, quindi posso iniettare un oggetto falso al posto di ValidationError?

Posso creare un AbstractValidationErrorFactory e iniettare invece la factory. Funzionerebbe, ma sembra che finirò per creare tonnellate di piccole fabbriche e interfacce di fabbrica, per ogni dipendenza di questo tipo. C'è un modo migliore?

    
posta JW01 31.01.2011 - 21:14
fonte

2 risposte

4

La modifica più semplice per rendere testabile la tua unità di classe è

  1. (estrai il codice di creazione in un nuovo metodo (virtuale) - lo hai già)
  2. sottoclasse la classe testata, sovrascrivendo il metodo di creazione per creare un oggetto fittizio adatto invece di quello reale
  3. scrivi i tuoi test unitari: -)

Certo, non è molto carino. Ma ti consente di coprire la classe con test di unità, dopo di che puoi iniziare a rifactoring verso il design ideale, senza timore di infrangere codice con modifiche più profonde.

Riferimento obbligatorio: Funzionante in modo efficace con il codice legacy .

Riguardo a questo disegno ideale è difficile dire molto, dato che il tuo esempio manca di dettagli e contesto. Se ci parli di più su ciò che stai cercando di testare e qual è il ruolo della classe testata, potremmo essere in grado di aiutarti di più.

    
risposta data 31.01.2011 - 21:21
fonte
2

Normalmente la soluzione per questo problema è il modello Provider:

public class Validator {
    public Provider<ValidationError> errorProvider;

    public void addError(String text) {
        errors.add(errorProvider.get(text));
    }
}

Il fornitore è qualcosa di simile alla fabbrica. In questo caso restituirà nuovo ValidationError ogni volta che viene chiamato get .

È possibile trovare ulteriori informazioni nel Iniezione delle dipendenze nella sezione 3.3.2 (Reiniezione con il modello Provider) .

Guice , per exampe, ha Provider per questo. Se desideri qualcosa di più sofisticato, puoi utilizzare AssistedInject .

    
risposta data 31.01.2011 - 22:02
fonte

Leggi altre domande sui tag