Quando la proprietà è definita nel database di produzione (o un clone per il test), questo non è un test unitario . Un test unitario verifica un'unità di lavoro e non richiede un particolare stato esterno per funzionare. Ciò presuppone che Offer1
nel database sia definito come un'offerta esclusivamente maschile. Questo è uno stato esterno. Quindi questo è più un test di integrazione , in particolare un sistema o un test di accettazione . Si noti che i test di accettazione spesso non sono scritti (non eseguiti in un framework di test ma eseguiti manualmente da esseri umani).
Quando la proprietà è definita nel modello di dominio con if
un'istruzione, lo stesso test è un unit test. E potrebbe essere fragile. Ma il vero problema è che il codice è fragile. Come regola generale, il codice sarà più resiliente se il comportamento aziendale è configurabile anziché codificato. Perché una distribuzione urgente per correggere un piccolo errore di codifica dovrebbe essere rara. Ma un requisito aziendale che cambia senza preavviso è solo un martedì (qualcosa che accade settimanalmente).
È possibile che si stia utilizzando un framework di unit test per eseguire il test. Ma i framework di unit test non si limitano all'esecuzione di unit test. Possono anche eseguire test di integrazione.
Se stavi scrivendo un test unitario, creeresti entrambi person
e offer1
da zero senza fare affidamento sullo stato del database. Qualcosa di simile a
[Fact]
public void ReturnsFalseWhenGivenAPersonWithAGenderOfFemale()
{
var personId = Guid.NewGuid();
var gender = "F";
var person = new Person(personId, gender);
var id = Guid.NewGuid();
var offer1 = new Offer1(id, "ReturnsFalseWhenGivenAPersonWithAGenderOfFemale");
offer1.markLimitedToGender("M");
Assert.False(offer1.IsEligible(person));
}
Si noti che ciò non cambia in base alla logica aziendale. Non sta affermando che offer1
rifiuta le femmine. Sta facendo offer1
il tipo di offerta che rifiuta le femmine.
È possibile creare e configurare il database come parte del test. In C #, utilizzando NUnit o in JUnit di Java, si imposta il database in un Setup
metodo. Presumibilmente il tuo framework di test ha una nozione simile. In questo metodo, è possibile inserire record nel database con SQL.
Se è difficile scrivere un codice che sostituisca un database di prova con il database di produzione, ciò sembra una debolezza del test nell'applicazione. Per i test, sarebbe meglio usare qualcosa come l'iniezione di dipendenza che consente la sostituzione. Quindi è possibile scrivere test indipendenti dalle attuali regole aziendali.
Un vantaggio collaterale di questo è che spesso è più facile per il proprietario dell'azienda (non necessariamente il proprietario dell'azienda, più come la persona responsabile di questo prodotto nella gerarchia aziendale) configurare direttamente le regole aziendali. Perché se si dispone di questo tipo di framework tecnico, è facile consentire al proprietario dell'azienda di utilizzare un'interfaccia utente (UI) per configurare l'offerta. Il proprietario dell'azienda selezionerebbe la limitazione nell'interfaccia utente ed emetterebbe la markLimitedToGender("M")
chiamata. Quindi, quando l'offerta viene mantenuta nel database, questa viene archiviata. Ma non è necessario archiviare l'offerta per utilizzarla. Quindi i tuoi test potrebbero creare e configurare un'offerta che non esiste nel database.
Nel tuo sistema come descritto, il proprietario dell'azienda dovrebbe inviare una richiesta al gruppo tecnico, che emetterebbe l'SQL appropriato e aggiornerà i test. Oppure il gruppo tecnico deve modificare il codice e i test (o i test, quindi il codice). Sembra un approccio piuttosto pesante. Puoi farlo. Ma il tuo software (non solo i tuoi test) sarebbe meno fragile se non dovessi farlo.
TL; DR : puoi scrivere test come questo, ma potresti essere meglio scrivere il tuo software in modo da non doverlo fare.