unit-testing
Testdubblar
Sök…
Anmärkningar
Vid testning är det ibland användbart att använda ett testdubbla för att manipulera eller verifiera beteendet hos systemet som testas. Dubblorna överförs eller injiceras i klassen eller metoden som testas istället för exempel på produktionskod.
Använda en stub för att leverera konserverade svar
En stub är en dubbel med låg viktprov som ger konserverade svar när metoder kallas. Där en klass under test förlitar sig på ett gränssnitt eller basklass kan en alternativ "stub" -klasse implementeras för testning som överensstämmer med gränssnittet.
Så antar följande gränssnitt,
public interface IRecordProvider {
IEnumerable<Record> GetRecords();
}
Om följande metod skulle testas
public bool ProcessRecord(IRecordProvider provider)
En stubklass som implementerar gränssnittet kan skrivas för att returnera kända data till metoden som testas.
public class RecordProviderStub : IRecordProvider
{
public IEnumerable<Record> GetRecords()
{
return new List<Record> {
new Record { Id = 1, Flag=false, Value="First" },
new Record { Id = 2, Flag=true, Value="Second" },
new Record { Id = 3, Flag=false, Value="Third" }
};
}
}
Denna stubimplementering kan sedan tillhandahållas till det testade systemet för att påverka dess beteende.
var stub = new RecordProviderStub();
var processed = sut.ProcessRecord(stub);
Använda ett hålande ramverk som stubb
Termerna Mock och Stub kan ofta bli förvirrade. En del av orsaken till detta är att många hånliga ramar också ger stöd för att skapa Stubs utan verifieringssteget som är associerat med Mocking.
I stället för att skriva en ny klass för att implementera en stub som i exemplet "Använda en stub för att tillhandahålla konserverade svar", kan hånliga ramar användas istället.
Använda Moq:
var stub = new Mock<IRecordProvider>();
stub.Setup(provider => provider.GetRecords()).Returns(new List<Record> {
new Record { Id = 1, Flag=false, Value="First" },
new Record { Id = 2, Flag=true, Value="Second" },
new Record { Id = 3, Flag=false, Value="Third" }
});
Detta uppnår samma beteende som den handkodade stubben och kan levereras till systemet som testas på liknande sätt:
var processed = sut.ProcessRecord(stub.Object);
Använda ett hålande ramverk för att validera beteende
Spott används när det är nödvändigt att verifiera interaktioner mellan systemet under test och testdubblar. Man måste vara försiktig för att undvika att skapa alltför spröda test, men hån kan vara särskilt användbara när metoden för att testa helt enkelt orkestrerar andra samtal.
Detta test verifierar att när metoden under testet kallas ( ProcessRecord
), att servicemetoden ( UseValue
) kallas för Record
där Flag==true
. För att göra detta sätter det upp en stubbe med konserverad data:
var stub = new Mock<IRecordProvider>();
stub.Setup(provider => provider.GetRecords()).Returns(new List<Record> {
new Record { Id = 1, Flag=false, Value="First" },
new Record { Id = 2, Flag=true, Value="Second" },
new Record { Id = 3, Flag=false, Value="Third" }
});
Sedan sätter det upp en håna som implementerar IService
gränssnittet:
var mockService = new Mock<IService>();
mockService.Setup(service => service.UseValue(It.IsAny<string>())).Returns(true);
Dessa levereras sedan till det testade systemet och metoden som ska testas kallas.
var sut = new SystemUnderTest(mockService.Object);
var processed = sut.ProcessRecord(stub.Object);
Spottet kan sedan förhöras för att verifiera att det förväntade samtalet har gjorts till det. I detta fall ett samtal till UseValue
, med en parameter "Second", som är värdet från posten där Flag==true
.
mockService.Verify(service => service.UseValue("Second"));