2009-07-06 7 views
7

EsempioDevo scrivere un test unitario per un metodo all'interno della classe di servizio che chiama solo un metodo all'interno della classe repository?

ho una classe repository (DAL):

public class MyRepository : IMyRepository 
{ 
    public void Delete(int itemId) 
    { 
     // creates a concrete EF context class 
     // deletes the object by calling context.DeleteObject() 
    } 

    // other methods 
} 

Ho anche una classe di servizio (BLL):

public class MyService 
{ 
    private IMyRepository localRepository; 

    public MyService(IMyRepository instance) 
    { 
     this.localRepository = instance; 
    } 

    public void Delete(int itemId) 
    { 
     instance.Delete(itemId); 
    } 

    // other methods 
} 

Creazione di un test di unità per MyRepository avrebbe preso molto più tempo che implementarlo, perché dovrei prendere in giro il contesto di Entity Framework.

Tuttavia, la creazione di un test di unità per MyService sembra assurda, perché chiama solo nel repository. Tutto quello che potevo verificare è verificare se effettivamente ha chiamato il metodo Delete del repository.

Domanda

Come ti suggerisco di unit test questi paio di metodi di eliminazione. Entrambi? Uno? Nessuna? E cosa testeresti?

risposta

1

Sì, scriverò sicuramente un test unitario per il livello di servizio. Il motivo è perché, non stai solo testando che la tua implementazione funziona ora, ma stai anche testando che continuerà a funzionare in futuro.

Questo è un concetto fondamentale da comprendere. Se qualcuno arriva più tardi e cambia il tuo ServiceLayer, e non c'è un test unitario, come puoi verificare che la funzionalità continui a funzionare?

Scriverò anche test per il DAL, ma li inserirò in un assembly separato chiamato DataTests o qualcosa del genere. Lo scopo qui è quello di isolare le tue preoccupazioni tra gli assembly. I test di unità non dovrebbero riguardare il tuo DAL, davvero.

+0

Ma se collaudo unitamente al metodo Service.Delete(), tutto quello che posso fare è verificare che chiami il metodo Repository.Delete(). Non riesco a controllare alcun dato, perché la manipolazione dei dati avviene nel repository. Altre (future) complessità non saranno incluse nel test. –

+1

@Robert Questo non è del tutto corretto. Dovresti creare un oggetto IMyRepository fittizio. Dopo averlo fatto, puoi configurare il tuo simulato in modo che quando il livello di servizio chiama delete su di esso, puoi verificare che l'eliminazione sia chiamata correttamente sul simulatore. Pertanto, stai testando la funzionalità Service.Delete senza testare il Repository.Delete. – Joseph

1

Sì, entrambi.

IMyRepository mock = ...; 
// create Delete(int) expectation 

MyService service = new MyService(mock); 
service.Delete(100); 

// Verify expectations 

In questo momento il metodo Delete può solo chiamare il metodo Delete sul repository, ma ciò non significa che lo farà sempre. Volete avere dei test unitari per questo in parte per verificare che si comporti correttamente e in parte come modo per definire le vostre specifiche su come il repository deve funzionare.

È anche necessario eseguire un test per verificare che il costruttore generi un'eccezione se il repository è nullo. Potresti anche avere altre convalide da eseguire qui in questo metodo, come ID non negativo o ID diverso da zero. Forse questo non accade qui, lo rende parte delle specifiche creando test che verificano i comportamenti previsti.

Sembrano banali ma posso solo garantire che cambierà un giorno e le vostre aspettative e specifiche potrebbero non essere verificate.

+0

Bene, tutto ciò che hai fatto nel tuo esempio è stato un test Service.Delete(). Hai deriso il mio repository e testato il servizio che effettivamente chiama nel repository. –

+0

Quello che intendevo con il mio commento precedente è che hai detto "entrambi" ma hai solo scritto codice per testare il livello di servizio. Ma sì, il servizio è testato nel tuo caso. –

+0

Scusami, avrei quindi un altro set di test per testare il repository concreto, che potrebbe essere più difficile dal momento che probabilmente sei dipendente da librerie di terze parti e altri livelli. Questi test potrebbero essere più simili ai test di integrazione. Quindi entrambi cercano di ottenere una copertura totale del codice. Ma non penso che si possa trascurare questa classe poiché questa è l'astrazione con cui si codificherà la tua app. –

0

Creare il test per il servizio. Attualmente tutto ciò che fa è chiamare nel metodo Repository Delete; tuttavia, non dovresti preoccupartene. Che cosa succede se più tardi accade qualcosa e la funzionalità diventa molto più complicata? Non vuoi avere un codice di test unitario che ti assicuri che la funzionalità funzioni ancora come previsto?

Se stai esponendo il tuo Elimina tramite il tuo Servizio, ti aspetti che abbia un effetto. Scrivi un test unitario per testare quell'effetto. A seconda delle tue esigenze particolari, direi che potrebbe non essere necessario eseguire un test sull'eliminazione del repository, in particolare se tale funzionalità viene esercitata come parte della funzionalità di eliminazione dei servizi, ma in realtà tutto dipende dal livello di copertura che hai sto cercando.

+0

Ma se collaudo unitamente al metodo Service.Delete(), tutto quello che posso fare è verificare che chiami il metodo Repository.Delete(). Non riesco a controllare alcun dato, perché la manipolazione dei dati avviene nel repository. –

+0

È sufficiente sapere che Service.Delete() chiama Repository.Delete()? Allora stai bene con solo Service.Delete(). Hai bisogno di controllare i dati? Quindi avrai bisogno di un certo livello di derisione per verificare che i dati vengano modificati. –

0

Inoltre, se avessi creato questo codice con TDD, avresti avuto un test. In realtà è importante sapere se le persone possono chiamare Elimina tramite il tuo servizio, quindi in realtà devi testarlo.

0

Secondo me è necessario testare entrambi. Forse puoi fare la classe di contesto EF di creazione in un factory separato che può essere testato più facilmente e prendere in giro la classe di contesto per i test di MyRepository. Questo sarà più facile e usare una fabbrica per creare un contesto di chiamate sembra essere per me molto utile.

+0

Vorrei, ma come posso google in rete, il contesto Entity Framework beffardo è un dolore in un ... –