Quello che fa un repository è tradurre dal tuo dominio nel tuo framework DAL, come NHibernate o Doctrine, o le tue classi di esecuzione SQL. Ciò significa che il tuo repository chiamerà metodi su detto framework per svolgere i suoi compiti: il tuo repository costruisce le query necessarie per recuperare i dati. Se non si utilizza un framework ORM (spero che tu sia ...), il repository sarebbe il luogo in cui vengono create le istruzioni SQL non elaborate.
Il più semplice di questi metodi è il salvataggio: nella maggior parte dei casi questo passerà semplicemente l'oggetto dal repository all'unità di lavoro (o alla sessione).
public void Save(Car car)
{
session.Save(car);
}
Ma diamo un'occhiata a un altro esempio, ad esempio recuperare un'auto dal suo ID. Potrebbe sembrare
public function GetCarWithId(String id)
{
return Session.QueryOver<Car>()
.Where(x => x.Id == id)
.SingleOrDefault();
}
Ancora non troppo complesso, ma puoi immaginarlo a più condizioni (procurami tutte le macchine prodotte dopo il 2010 per tutti i marchi del gruppo "Volkswagen"), questo diventa complicato. Quindi, in vero stile TDD, devi testarlo. Esistono diversi modi per farlo.
Opzione 1: deride le chiamate effettuate al framework ORM
Certo, puoi deridere l'oggetto Session e semplicemente affermare che vengono fatte le chiamate giuste. Mentre questo testa il repository, non è realmente test- driven perché stai solo testando che il repository internamente abbia l'aspetto che desideri. Il test in pratica dice "il codice dovrebbe apparire così". Tuttavia, è un approccio valido ma sembra che questo tipo di test abbia un valore molto scarso.
Opzione 2: (ri) compilare il database dai test
Alcuni framework DAL offrono la possibilità di creare la struttura completa del database in base ai file di mapping creati per mappare il dominio sulle tabelle. Per questi framework il modo per testare i repository è spesso quello di creare il database con un database in-memory nella prima fase del test e aggiungere oggetti usando il framework DAL al database in-memory. Successivamente, è possibile utilizzare il repository sul database in memoria per verificare se i metodi funzionano. Questi test sono più lenti, ma molto validi e guidano i tuoi test. Richiede un po 'di collaborazione dal tuo framework DAL.
Opzione 3: test su un database effettivo
Un altro approccio è testare su un database reale e isolare il più semplice. Puoi farlo in diversi modi: circonda i tuoi test con una transazione, pulisci manualmente (non sarebbe molto difficile da mantenere), ricostruisci completamente il database dopo ogni passaggio ... A seconda dell'applicazione che stai costruendo questo può o potrebbe non essere fattibile. Nelle mie applicazioni posso costruire completamente un database di sviluppo locale dal controllo del codice sorgente e i miei unittest sui repository utilizzano le transazioni per isolare completamente i test l'uno dall'altro (transazione aperta, inserimento dati, repository di test, transazione di rollback). Ogni build prima imposta il database di sviluppo locale e quindi esegue unittest isolati per le transazioni per i repository su quel database di sviluppo locale. E'
Non testare il DAL
Se si utilizza un framework DAL come NHibernate, evitare la necessità di testare tale framework. Puoi testare i tuoi file di mapping salvando, recuperando e confrontando un oggetto di dominio per assicurarti che tutto sia a posto (assicurati di disabilitare qualsiasi tipo di memorizzazione nella cache) ma non è così richiesto come molti altri test che dovresti scrivere. Tendo a farlo principalmente per le raccolte sui genitori con condizioni sui bambini.
Durante il test del ritorno dei tuoi repository puoi semplicemente verificare se alcune proprietà identificative sul tuo oggetto dominio corrispondono. Questo può essere un ID ma nei test è spesso più utile controllare una proprietà leggibile dall'uomo. Nel 'fammi vedere tutte le macchine costruite dopo il 2010 ....' questo potrebbe semplicemente verificare che vengano restituite cinque macchine e che le targhe siano 'inserisci la lista qui'. Un ulteriore vantaggio è che ti costringe a pensare all'ordinamento E il tuo test forza automaticamente l'ordinamento. Sareste sorpresi dal numero di applicazioni ordinate più volte (restituite ordinate dal database, ordinate prima di creare un oggetto vista e quindi ordinate l'oggetto vista, tutto sulla stessa proprietà per ogni evenienza ) o assumete implicitamente l'ordinamento del repository e rimuovete accidentalmente che da qualche parte erano lungo la strada, rompendo l'interfaccia utente.
"Unit test" è solo un nome
A mio avviso, i test unitari non dovrebbero per lo più raggiungere il database. Si crea un'applicazione in modo tale che ogni parte di codice che necessita di dati da un'origine lo faccia con un repository e quel repository viene iniettato come dipendenza. Ciò consente un facile derisione e tutta la bontà del TDD che desideri. Ma alla fine vuoi assicurarti che i tuoi repository svolgano i loro compiti e se il modo più semplice per farlo è colpire un database, beh, così sia. Ho da tempo abbandonato l'idea che "i test unitari non dovrebbero toccare il database" e ho appreso che ci sono ragioni molto reali per farlo. Ma solo se puoi farlo automaticamente e ripetutamente. E il tempo che chiamiamo tale test un "test unitario" o un "test di integrazione" è controverso.