Methoden für das Hinzufügen von Daten zu Mock-Datenbanken in C# Unit-Tests
Dieser Beitrag soll mehr eine Diskussion-starter, ich bin etwas neu auf unit-Tests und TDD.
Ich bin derzeit am schreiben von unit tests für eine .NET-Prozess, der eine Interaktion mit mehreren Datenbanken, und bin mit mock-Datenbank Kontexten in einem Versuch zu decken verschiedene Grenzfälle, die in meinen tests, überprüfen Sie die Ausnahmebehandlung im Programm selbst, unter anderem. That being said, einige meiner unit-tests verwenden Daten gültig sind, während andere dies nicht tun.
Ich bin auf der Suche nach feedback in Bezug auf die vorgeschlagene best-practices beim hinzufügen von gültigen/gefälschte Daten, um Ihre mock-Datenbank zusammenhängen. Ich habe gesehen, Menschen tun dies eine Reihe von Möglichkeiten (z.B. - implementieren von repository-Muster, das hinzufügen von mock-Daten .csv-Dateien und macht Sie Teil des Projekts, etc...).
Ich bin derzeit zu denken über die Verwendung eines repository-pattern für das hinzufügen Survey
Objekte der Surveys
Tisch in meinem Ziel-DB.
First off, ich habe das interface:
public interface ISurveyRepository
{
IQueryable<Survey> SurveySeries { get; }
}
Umgesetzt wird dies sowohl für den Spott fake/gültige Daten-repositories, wie erforderlich, durch unit-tests
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
Dann habe ich eine Klasse zu verbrauchen, diese Daten entweder gefälscht/gültige Daten, indem Sie übergeben eine Referenz auf die Serie im Konstruktor:
public class SurveySeriesProcessor
{
private ISurveyRepository surveyRepository;
public SurveySeriesProcessor( ISurveyRepository surveyRepository )
{
this.surveyRepository = surveyRepository;
}
public IQueryable<Survey> GetSurveys()
{
return surveyRepository.SurveySeries
}
}
Und kann sich dann an diese Objekte verwenden, die in den tests wie:
[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);
}
}
}
HINWEIS: ich weiß, dass im Beispiel-code zur Verfügung gestellt, die ich nicht unbedingt benötigen, um die Klassen der Umsetzung ISurveyRepository
Gegenzug die Serie als eine IQueryable<Survey>
(Sie könnte sehr gut sein List<Survey>
). Allerdings werde ich für die Erweiterung der Funktionalität der Schnittstelle und diese Klassen in der Zukunft heraus zu filtern, die gefälschte/gültig-Serie, basierend auf bestimmten Kriterien Hinzugefügt, LINQ-Abfragen, die ist, warum ich aus den repositories implementieren IQueryable<>
. Dies ist mock-up-code, der entwickelt wurde, vermitteln die grundlegenden Prinzipien dessen, was ich mir denke.
Mit all dem im Hinterkopf, was ich verlange ist:
- Haben Sie irgendwelche Vorschläge in Bezug auf alternative Ansätze, ich könnte in solchen Szenarien?
- Welche Methoden haben Sie in der Vergangenheit eingesetzt, was hat Euch gefallen/nicht gefallen? Was haben Sie gefunden, die waren am einfachsten zu pflegen?
- Gegeben, was ich gepostet habe, merkt Ihr Fehler in meiner Allgemeinen Ansatz für die unit-Tests? Manchmal habe ich das Gefühl, als ob ich schreiben unit-tests, die versuchen, zu viel Masse statt prägnant, elegant und auf den Punkt.
Dies ist gedacht, um etwas von einer offenen Diskussion. Bitte beachten Sie, dies ist der erste Satz von unit-tests, die ich jemals geschrieben habe (die ich gelesen habe, eine anständige Menge an Literatur zu dem Thema, jedoch).
InformationsquelleAutor Eric Stallcup | 2012-11-15
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich glaube, du bist auf einem guten Weg.
Persönlich, in der gleichen situation, wenn ich es mit einem repository-Stil-Muster,
Tatsächlich liefern mir die Informationen, die ich brauche, ich in der Regel eine TestObjects oder TestFakes Klasse auf die Bereitstellung der erforderlichen Daten auf Abruf.
Testen diese als solche:
Also dies liefert die Wiederverwendbarkeit des fake-Daten, indem es aus dem repository und in einen Platz der eigenen, das heißt, ich kann nennen diese Liste der Ponys irgendwo einen test benötigt eine Liste der Ponys, nicht nur dort, wo ein repository eingebunden ist.
Wenn ich bestimmte Daten für einen bestimmten testcase, werde ich umsetzen, sowas wie du hatte, aber ein bisschen mehr explizit, was diese Fake-repository ist für:
Ihnen genannten CSV-Dateien als gut - diese lebensfähig sein könnten (haben verwendet XML in der Vergangenheit), aber ich würde behaupten, dass das halten fake-Daten in einer CSV-oder XML ist einfach eine schlechtere version von halten Daten in eine lokale DB mit Hilfe von SQL CE oder etwas ähnliches. Aber diese beiden sind weniger wartbar und, entscheidend, die in Bezug auf unit-tests langsamer als die Verwendung von in-memory-fake-Objekte. Ich persönlich würde nicht mit einer Datei-basierten Ansatz mehr, es sei denn, ich wurde ausdrücklich die Prüfung der Serialisierung oder IO oder etwas.
Hoffe es ist etwas nützliches zu viel...
Froh, dass es sinnvoll war.
InformationsquelleAutor Greg Smith