2010-05-26 3 views
6

Sto iniziando con i test delle unità e sto provando a fare qualche TDD. Ho letto un bel po 'sull'argomento e ho scritto alcuni test. Voglio solo sapere se il seguente è l'approccio giusto.Come si deve testare l'invio di e-mail da un controller?

Desidero aggiungere la solita funzione "contattaci" sul mio sito web. Sai qual è la cosa, l'utente compila un modulo con il loro indirizzo email, inserisce un breve messaggio e preme un pulsante per inviare il modulo indietro.

I raccoglitori modello fanno le loro cose e il mio metodo di azione accetta i dati inviati come modello. Il metodo di azione analizzerebbe quindi il modello e userà smtp per inviare una e-mail all'amministratore del sito web che lo informa che qualcuno ha compilato il modulo di contatto sul proprio sito.

Ora per la domanda .... Per testare questo, dovrei essere proprio la creazione di un'interfaccia IMessageService che ha un metodo Invia (emailAddress, messaggio) per accettare l'indirizzo email e il corpo del messaggio. Implementa l'intefaccia in una classe concreta e lascia che quella classe si occupi di smtp e in realtà invii la posta.

Se aggiungo l'interfaccia come parametro al costruttore del controller, posso utilizzare DI e IoC per iniettare la classe concreta nel controller. Ma quando collaudo unità posso creare una versione falsa o finta del mio IMessageService e fare asserzioni su quello.

La ragione per cui chiedo è che ho visto altri esempi di persone che generano interfacce per SmtpClient e che poi lo prendono in giro. C'è davvero bisogno di andare così lontano o non capisco questa roba?

risposta

2

Avresti ancora bisogno di testare la tua classe che invoca il mailer. Ti suggerisco di voler fare un po 'di entrambi. Generalmente creo un'interfaccia IMailClient e un wrapper attorno a SmtpClient che implementa l'interfaccia. Utilizzare (e iniettare) l'interfaccia in una classe proxy che sa come costruire il messaggio e inviarlo (potrebbe avere diversi metodi di tipo factory in grado di costruire più tipi diversi di messaggi). Lo shim attorno allo SmtpClient dovrebbe essere proprio questo, quindi non c'è bisogno che l'unità lo collauda. È possibile prendere in giro lo shim durante il test della classe proxy e prendere in giro la classe proxy durante il test dei controller.

+0

Sono d'accordo, e sarà probabilmente utile non appena avrai bisogno di IMailClientAsync che puoi scambiare. – Hal

1

L'apologia che descrivi ha funzionato bene per me in passato. Ho lavorato a un progetto che si interfacciava con l'API del servizio web MS Dynamics CRM. Volevo testare il mio codice unitario, ma non desideravo testare il servizio web. Ho seguito l'esatto processo che descrivi, ma con il servizio web deriso piuttosto che la consegna della posta. Ha funzionato molto bene.

1

Sei sulla strada giusta, questo è l'approccio che dovresti usare. Probabilmente gli esempi a cui ti riferisci, sono persone che la seguono in modo duro/sbagliato ... o sono esempi su come puoi gestire una grande base di codice legacy.

L'iniezione del meccanismo per recapitare il messaggio è flessibile e può essere facilmente riutilizzata in altri scenari. Uno di questi scenari è la diagnostica, se si ha un server di sviluppo probabilmente non si desidera che tocchi di posta ininterrottamente, passando alla classe iniettata si può avere output su un file o semplicemente su Debug.Write.

ps. ti consigliamo comunque di testare la tua classe SmptDeliver, ma sarebbe un test di integrazione focalizzato che puoi fare su quella classe indipendentemente dal resto del codice.

1

Penso che sia sulla strada giusta. Non preoccuparti dei server smtp o di qualsiasi altra cosa. Basta testare l'unità di ciò che ti serve. Lascia che i test ti dica ciò di cui hai bisogno.Quando raggiungi il test dell'effettivo Send(emailAddress, message), puoi preoccuparti di come effettivamente manderai il messaggio all'amministratore.