Ogni tanto, nello sviluppo software, emerge qualche meme come ad esempio: tutte le dipendenze devono essere
disaccoppiate tramite un interface, tutte gli oggetti devono essere creati tramite factory, l'accesso ad un database
deve avvenire tramite un ORM, il TDD genera un buon design ecc.
Cosa hanno in comune tutte le frasi precedenti? Semplice: creano scorciatoie per evitare di pensare.
Sarebbe bello se potessimo scrivere codice seguendo alla lettera un manuale, ma sarebbe anche terribilmente noioso
e probabilmente verremmo sostituiti da qualche tipo di bot.
Prendiamo la prima affermazione: tutte le dipendenze devono essere disaccoppiate tramite un interface
e cerchiamo di capire da dove nasce questa esigenza. Il vantaggio di avere le dipendenze solo tramite interfacce dovrebbe essere quello
di rendere più testabile le nostre classi. Ma è l'unico modo? Ed è il più semplice?
Proviamo a fare un esempio. Supponiamo di voler testare il metodo SayHello:
var display = new Display();
var greeting = new Greeting(display);
greeting.SayHello();
L'implementazione di Greeting è la seguente:
public class Greeting
{
private readonly Display _display;
public Greeting(Display display)
{
_display = display;
}
public void SayHello()
{
_display.Show("Hello!");
}
}
Mentre l'implementazione di display è la seguente:
public class Display
{
public void Show(string text)
{
Console.WriteLine(text);
}
}
Sembra proprio il tipico esempio da manuale in cui si estrae l'interfaccia IDisplay e tramite la libreria di mocking preferita testo le interazioni
di Greeting con Display. Esiste un'alternativa?
La classe Console eredita da TextWriter, anche la classe StringWriter eredita da TextWriter. Proviamo quindi a passare la
Console in costruzione a Display:
public class Display
{
private readonly TextWriter _textWriter;
public Display(TextWriter textWriter)
{
_textWriter = textWriter;
}
public void Show(string text)
{
_textWriter.WriteLine(text);
}
}
Ora modfichiamo il main:
var display = new Display(Console.Out);
var greeting = new Greeting(display);
greeting.SayHello();
A questo punto possiamo scrivere il test:
var stringWriter = new StringWriter();
var greeting = new Greeting(new Display(stringWriter));
greeting.SayHello();
Assert.That(stringWriter.ToString(), Is.EqualTo("Hello!"));
In questo modo abbiamo fatto un test più solido rispetto a testare l'interazione con un interfaccia ed il codice è più semplice.