Les méthodes permettant d'Ajouter des Données pour se Moquer de bases de données en C# Tests Unitaires
Ce post est destiné à être davantage une discussion-démarreur, comme je suis un peu nouveau pour les tests unitaires et TDD.
Je suis présentement à l'écriture de tests unitaires pour une .NET processus qui interagit avec plusieurs bases de données, et suis en utilisant la maquette de la base de données des contextes dans une tentative de couvrir les différents cas de bord à l'intérieur de mes tests, vérifier la gestion des exceptions dans le programme lui-même, entre autres choses. Cela étant dit, certains de mes tests unitaires utilisation des données valides, tandis que d'autres ne le font pas.
Je suis à la recherche de commentaires, en termes de meilleures pratiques lors de l'ajout d'valide/faux les données de votre maquette de la base de données des contextes. J'ai vu des gens faire un certain nombre de façons (ex - mettre en œuvre un modèle de référentiel, l'ajout de se moquer de données .les fichiers csv et de les rendre le cadre du projet, etc...).
Je suis actuellement une réflexion sur l'utilisation d'un modèle de référentiel pour l'ajout de Survey
objets à la Surveys
table dans ma cible DB.
Tout d'abord, j'ai l'interface:
public interface ISurveyRepository
{
IQueryable<Survey> SurveySeries { get; }
}
Ceci est mis en œuvre à la fois pour les moqueries faux/valide référentiels de données en tant que de besoin par les tests unitaires
class FakeSurveyRepository : ISurveyRepository
{
private static IQueryable<Survey> fakeSurveySeries = new List<Survey> {
new Survey { id = 1, SurveyName="NotValid1", SurveyData="<data>fake</data>"},
new Survey { id = 2, SurveyName="NotValid2", SurveyData="<data>super fake</data>"},
.........,
new Survey {id = 10, SurveyName="NotValid10", SurveyData="<data>the fakest</data>" }
}.AsQueryable();
public IQueryable<Survey> SurveySeries
{
get { return fakeSurveySeries; }
}
}
//RealSurveyRepository : ISurveyRepository is similar to this, but with "good" data
J'ai ensuite une classe à utiliser ces données pour soit faux/données valides en étant passé à une référence à la série dans le constructeur:
public class SurveySeriesProcessor
{
private ISurveyRepository surveyRepository;
public SurveySeriesProcessor( ISurveyRepository surveyRepository )
{
this.surveyRepository = surveyRepository;
}
public IQueryable<Survey> GetSurveys()
{
return surveyRepository.SurveySeries
}
}
Et peut ensuite utiliser ces objets dans mes tests, tels que:
[TestClass]
public class SurveyTests
{
[TestMethod]
WhenInvalidSurveysFound_SurveyCopierThrowsInvalidSurveyDataErrorForEach()
{
//create mocking DB context and add fake data
var contextFactory = new ContextFactory( ContextType.Mocking );
var surveySeriesProcessor = new SurveySeriesProcessor( new FakeSurveyRepository() );
foreach(Survey surveyRecord in surveySeriesProcessor.GetSurveys() )
{
contextFactory.TargetDBContext.Surveys.AddObject( surveyRecord );
}
//instantiate object being tested and run it against fake test data
var testSurveyCopier = new SurveyCopier( contextFactory );
testSurveyCopier.Start();
//test behavior
List<ErrorMessage> errors = testSurveyCopier.ErrorMessages;
errors.Count.ShouldEqual( surveySeriesProcessor.GetSurveys().Count );
foreach(ErrorMessage errMsg in errors)
{
errMsg.ErrorCode.ShouldEqual(ErrorMessage.ErrorMessageCode.InvalidSurveyData);
}
}
}
NOTE: je me rends compte que, dans l'exemple de code fourni je n'ai pas forcément besoin de faire les classes de la mise en œuvre de ISurveyRepository
retour de la série comme un IQueryable<Survey>
(ils pourraient très bien être List<Survey>
). Cependant, je vais étendre les fonctionnalités de l'interface et de ces classes dans l'avenir pour filtrer les faux/valides des séries sur certains critères ajoutés à des requêtes LINQ, c'est pourquoi j'ai fait les référentiels de mettre en œuvre IQueryable<>
. C'est de la maquette du code conçu pour transmettre les principes de base de ce que je pense.
Avec tout cela à l'esprit, ce que je vous pose est:
- Avez-vous des suggestions en ce qui concerne d'autres approches que je pouvais prendre dans de tels scénarios?
- Quelles sont les méthodes que vous avez employées dans le passé, qu'avez-vous aimé/pas comme eux? Qui avez-vous trouvé le plus facile à maintenir?
- Compte tenu de ce que j'ai posté, avez-vous remarqué des défauts dans mon approche générale de l'unité de test? Parfois j'ai l'impression d'écrire des tests unitaires qui tentent de couvrir trop de terrain au lieu d'être concis, élégant, et à-le-point.
C'est censé être un peu d'une discussion ouverte. Veuillez garder à l'esprit, c'est la première série de tests unitaires que j'ai jamais écrit (j'ai lu une quantité décente de la littérature sur le sujet, cependant).
Vous devez vous connecter pour publier un commentaire.
Je pense que tu es sur une bonne piste.
Personnellement, dans la même situation, si j'avais affaire à un référentiel de style de motif,
À réellement me fournir les données dont j'ai besoin, j'en général de créer une TestObjects ou TestFakes classe à fournir les données nécessaires à la demande.
Et de tester avec ce en tant que tel:
Si cette offre réutilisabilité des données fausses, en les gardant hors de l'référentiel et dans un endroit propre, ce qui signifie que je peux appeler cette liste des poneys partout un test nécessite une liste des poneys, et non pas seulement lorsqu'un dépôt est impliqué.
Si j'ai besoin de données spécifiques pour un cas de test, je vais mettre en place quelque chose comme vous l'avez fait, mais être un peu plus explicite sur ce que ce Faux référentiel est pour:
Vous avez mentionné les fichiers CSV ainsi - ce qui pourrait être viable (ont utilisé les données XML dans le passé), mais je dirais que la tenue de fausses données dans un fichier CSV ou XML est juste un mal de version de conservation des données localisées DB à l'aide de SQL CE ou l'équivalent. Toutefois, ces deux sont de moins en moins facile à gérer et, surtout, en termes de tests unitaires, plus lent qu'en mémoire de faux objets. Personnellement, je ne voudrais pas utiliser un fichier de la base de l'approche plus à moins que j'ai été tester la sérialisation ou IO ou quelque chose.
Espère qu'il y a quelque chose d'utile parmi tous beaucoup...