Per parametri non contrattuali, intendo i parametri che non sono interfacce o dipendenze del servizio, qualcosa come class Person(string name)
.
Sto scrivendo un'applicazione di scraping di una pagina web e finora l'ho scritta nell'ordine sbagliato (da qui la creazione di questa domanda). Ho creato una classe per analizzare documenti HTML (dal formato stringa) e darmi tutti gli URL e le immagini in esso contenuti.
Quella classe ha la seguente descrizione:
public class PageParser
{
private readonly string _html;
public PageParser(string html) {
_html = html;
}
public IEnumerable<string> GetImages() {
/* not important */
}
public IEnumerable<string> GetLinks() {
/* not important */
}
}
Questo codice funziona alla grande, testato unitamente, copertura al 100%, ecc ... Il problema ora è come scrivo unit test per il codice che usa questa classe senza preoccuparsi del costruttore di questa classe. Ho solo bisogno che questa nuova classe funzioni con il comportamento di PageParser
.
Lo pseudo codice per questa nuova funzionalità è il seguente:
public Report CreateReport(string url)
{
var html = _webClient.DownloadString(url);
var parser = new PageParser(html);
var images = parser.GetImages();
var links = parser.GetLinks();
var relevantLinks = links.Where(l => l.Contains('something'));
return _reportBuilder.Create(images, relevantLinks);
}
Il problema che ho è che non voglio avere un gruppo di test unitari che abbiano documenti HTML di dimensioni epiche per tutti i miei vari casi di test che il metodo CreateReport
può avere.
Le opzioni che ho trovato sono:
1) Lascia tutto come è
Lascia la struttura della classe così com'è, vivi semplicemente con i test con variabili di configurazione grandi
2) Esporre il parser di pagina (+ interfaccia) da una Factory
Crea un'interfaccia per PageParser
e crea una fabbrica con l'interfaccia corrispondente.
interface IPageParserFactory
{
IPageParser Create(string html);
}
class PageParserFactory : IPageParserFactory
{
IPageParser Create(string html)
{
return new PageParser(html);
}
}
Quindi lo pseudo codice risultante apparirebbe come segue.
// ... download string
var pageParser = _pageParserFactory.Create(html);
// ... create report
3) Sposta il parametro html in ogni metodo e crea un'interfaccia (quindi ora la classe non ha dipendenze di costruzione)
interface IPageParser
{
IEnumerable<string> GetImages(string html);
IEnumerable<string> GetLinks(string html);
}
4) Qualcos'altro completamente
Se c'è un altro pattern che risolve questo problema mi piacerebbe saperlo.