Test dell'unità senza DI

3

Sto avviando un piccolo progetto ASP.NET MVC, ogni compito sulla scheda deve venire con test unitari. Il progetto è piccolo, solo poche pagine con non molta elaborazione, quindi ho deciso di non implementare DI. I miei pensieri essendo DI sono per progetti più grandi con grafici di dipendenza.

Tuttavia, ora sto scrivendo i test che mi ha fatto capire che i test sono più difficili. Non c'è nessuna iniezione del costruttore in corso, quindi il prendere in giro questi oggetti utilizzati dalle azioni del controller si sta rivelando problematico.

Se ci sono oggetti istanziati sull'azione a causa della mancanza di iniezione del contruttore, come si può prendere in giro per testarli?

    
posta James 18.08.2015 - 17:07
fonte

2 risposte

8

Ecco una domanda: sembra DI?

public class MyCar
{
    private IEngine _engine;

    public MyCar(IEngine engine)
    {
        _engine = engine;
    }

    public MyCar()
        : this(new MyV8Engine())
    {

    }
}

Dovrebbe, perché è DI. Dipendenza L'iniezione consiste nell'iniezione di una dipendenza in un oggetto, invece di porre l'onere di inventare o trovare la dipendenza dall'oggetto che lo richiede. DI non riguarda l'uso di un framework, è un modello di progettazione che risolve un problema .

È molto valido per le piccole applicazioni utilizzare l'iniezione basata su un costruttore e l'aggiunta di oggetti nei costruttori predefiniti. Il motivo per cui non lo vedi come esempio di DI è perché spesso il tuo grafico delle dipendenze diventa rapidamente molto grande e poco maneggevole e il passaggio a un framework DI diventa rapidamente vantaggioso man mano che l'applicazione cresce.

    
risposta data 19.08.2015 - 11:33
fonte
1

If there are objects being instantiated on the action due to lack of contructor injection how can you mock them to test?

Puoi refactoring il tuo codice per incapsulare tutto il codice che dovrebbe essere deriso in a separare i metodi protetti e quindi utilizzare partial-mocks per sostituire quella logica.

Esempio (in java)

Original

protected void moveFiles(File[] destFiles, File[] sourceFiles) {
    int pos = 0;
    while (pos < fileCount) {
        File sourceFile = sourceFiles[pos];
        File destFile = destFiles[pos];

        // do some processing. i.e. rename destFile if it already exists.

        // do the copy. the test should not execute this
        sourceFile.renameTo(destFile)
        pos++;
    }
}

refactoring:

protected void moveFiles(File[] destFiles, File[] sourceFiles) {
    int pos = 0;
    while (pos < fileCount) {
        File sourceFile = sourceFiles[pos];
        File destFile = destFiles[pos];

        // do some processing. i.e. rename destFile if it already exists.
        osFileMove(destFile, sourceFile);
        pos++;
    }
}

/** can be replaced by mock/stub in unittests */
protected boolean osFileMove(File destFile, File sourceFile) {
    return sourceFile.renameTo(destFile);
}

nel test puoi sostituire osFileMove con un falso (esempio usa java org.mockito.Mockito)

import static org.mockito.Mockito.*;

FileCommands sut;
@Before
public void setup() {
    sut = spy(new FileCommands());
    doReturn(true).when(sut).osCreateDirIfNeccessary(any(File.class));
    doReturn(true).when(sut).osFileCopy(any(File.class), any(File.class));
    doReturn(true).when(sut).osFileMove(any(File.class), any(File.class));
    doReturn(true).when(sut).osDeleteFile(any(File.class));
}

Se in seguito decidi di usare ioc puoi spostare le operazioni del file os-spcific osxXXXX in una classe separata più un'interfaccia

    
risposta data 19.08.2015 - 10:11
fonte

Leggi altre domande sui tag