unit-testing
Test Doubles
Recherche…
Remarques
Lors des tests, il est parfois utile d'utiliser un test double pour manipuler ou vérifier le comportement du système testé. Les doublons sont passés ou injectés dans la classe ou la méthode testée au lieu d'instances de code de production.
Utiliser un stub pour fournir des réponses prédéfinies
Un talon est un double test de poids léger qui fournit des réponses prédéfinies lorsque les méthodes sont appelées. Lorsqu'une classe testée repose sur une interface ou une classe de base, une classe de remplacement peut être implémentée pour les tests conformes à l'interface.
Donc, en supposant l'interface suivante,
public interface IRecordProvider {
IEnumerable<Record> GetRecords();
}
Si la méthode suivante devait être testée
public bool ProcessRecord(IRecordProvider provider)
Une classe de stub qui implémente l'interface peut être écrite pour renvoyer des données connues à la méthode testée.
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" }
};
}
}
Cette implémentation de stub peut alors être fournie au système testé pour influencer son comportement.
var stub = new RecordProviderStub();
var processed = sut.ProcessRecord(stub);
Utiliser un cadre moqueur comme souche
Les termes Mock et Stub peuvent souvent devenir confus. Cela s'explique en partie par le fait que de nombreux frameworks moqueurs prennent également en charge la création de stubs sans l'étape de vérification associée à Mocking.
Plutôt que d'écrire une nouvelle classe pour implémenter un stub, comme dans l'exemple "Utilisation d'un stub pour fournir des réponses prédéfinies", l'exemple peut être utilisé à la place des frameworks moqueurs.
En utilisant 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" }
});
Cela permet d'obtenir le même comportement que le stub codé à la main et peut être fourni au système sous test de la même manière:
var processed = sut.ProcessRecord(stub.Object);
Utiliser un cadre moqueur pour valider le comportement
Les simulations sont utilisées lorsqu'il est nécessaire de vérifier les interactions entre le système testé et les tests doubles. Des précautions doivent être prises pour éviter de créer des tests trop fragiles, mais se moquer peut être particulièrement utile lorsque la méthode de test consiste simplement à orchestrer d'autres appels.
Ce test vérifie que lorsque la méthode testée est appelée ( ProcessRecord
), la méthode de service ( UseValue
) est appelée pour le Record
où Flag==true
. Pour ce faire, il configure un stub avec des données prédéfinies:
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" }
});
Ensuite, il installe une maquette qui implémente l'interface IService
:
var mockService = new Mock<IService>();
mockService.Setup(service => service.UseValue(It.IsAny<string>())).Returns(true);
Ceux-ci sont ensuite fournis au système sous test et la méthode à tester est appelée.
var sut = new SystemUnderTest(mockService.Object);
var processed = sut.ProcessRecord(stub.Object);
Le simulacre peut alors être interrogé pour vérifier que l'appel prévu a été effectué. Dans ce cas, un appel à UseValue
, avec un paramètre "Second", qui correspond à la valeur de l'enregistrement où Flag==true
.
mockService.Verify(service => service.UseValue("Second"));