19 Stimmen

C# Unit Testing: Testen einer Methode, die MapPath verwendet

Zunächst einmal bin ich mir bewusst, dass diese Frage gefährlich nahe dran ist: Wie man MapPath in einem Einheitstest in C#

Ich hoffe jedoch, dass es eine andere Lösung gibt. Mein Problem folgt:

In meinem Code habe ich ein Objekt, das validiert werden muss. Ich erstelle Unit-Tests für jede Validierungsmethode, um sicherzustellen, dass sie korrekt validiert wird. Ich erstelle Scheindaten und lade sie in das Objekt, um sie dann zu validieren. Das Problem ist, dass innerhalb der Validierung, wenn ein Fehler auftritt, ein Fehlercode zugewiesen wird. Dieser Fehlercode wird verwendet, um Informationen über den Fehler aus einer Xml-Datei mit Server.MapPath zu sammeln. Beim Versuch, die Xml-Datei abzurufen, wird jedoch eine Ausnahme ausgelöst, was bedeutet, dass die Datei nicht gefunden werden kann.

Da MapPath in meinem Validierungscode ist, und nicht meine Unit-Test, wie bekomme ich meine Unit-Test, um den Pfad zu erkennen? Ergibt diese Frage einen Sinn?

Fehlerzeile (in meinem Validierungscode, NICHT in meinem Einheitstest):

XDocument xdoc = XDocument.Load(HttpContext.Current.Server.MapPath("App_Data/ErrorCodes.xml"));

Vereinfacht: Der Unit Test ruft eine Methode in meinem Programm auf, die Server.MapPath aufruft, was dann fehlschlägt.

15voto

Chris Missal Punkte 5696

Ich würde abstrahieren, die "Dateinamen-Anbieter" in eine Klasse, die einfach einen Speicherort zurückgibt, dann können Sie es viel, viel einfacher spöttisch.

public class PathProvider
{
    public virtual string GetPath()
    {
        return HttpContext.Current.Server.MapPath("App_Data/ErrorCodes.xml");
    }
}

Dann können Sie entweder direkt die PathProvider-Klasse verwenden...

PathProvider pathProvider = new PathProvider();
XDocument xdoc = XDocument.Load(pathProvider.GetPath());

Oder machen Sie es in Ihren Tests vor:

PathProvider pathProvider = new MockPathProvider(); // using a mocking framework
XDocument xdoc = XDocument.Load(pathProvider.GetPath());

11voto

Jeff Punkte 831

Nach gründlichem Googeln und der Hilfe eines Kollegen haben wir eine einfache Lösung gefunden, die bereits in .net integriert ist

Oberhalb der Unit-Tests, die auf den Validierungsprozess zugreifen, habe ich hinzugefügt:

 [TestMethod()]
 [HostType("ASP.NET")]
 [UrlToTest("http://localhost:###/upload_file.aspx")]
 [AspNetDevelopmentServerHost("Path To Web Application", "Path To Web Root")]

Das funktioniert perfekt. Wenn der Test aufgerufen wird, wird grundsätzlich die URL mit dem angegebenen Unit-Test beim Laden der Seite geladen. Da es sich um eine Website handelt, die nun den Unit-Test aufruft, hat die Validierung Zugriff auf Server.MapPath. Diese Lösung mag nicht für jeden funktionieren, aber für diesen Fall war sie perfekt. Vielen Dank an alle, die dazu beigetragen haben.

1voto

Lewis Punkte 5709

Versuchen Sie, Rhino Mocks oder ein alternatives Mocking-Framework zu verwenden, um den httpContext (oder andere abhängige Objekte) zu mocken Oder Sie könnten Ihre eigenen Mock-Objekte schreiben. Oder Sie schreiben eine MapPathWrapper-Klasse, erben von einer MapPathWrapperBase-Klasse für Ihre reale Umgebung und erstellen dann für Ihre Unit-Tests ein MockMapPathWrapper-Objekt.

Es sollte genügend Beispiele für Spott auf SO geben.

Hier ist eine Frage, die ich gestellt habe:

Wie man Rhino Mocks zum Mocking einer HttpContext.Application verwendet

UPDATE Ich habe nur Erfahrung tun dies mit dem Asp.Net MVC, mit Webforms I imagein es wäre viel schwieriger wegen des Fehlens einer HttpContextBase-Klasse.

1voto

dahlbyk Punkte 71222

Ich würde Methoden extrahieren, die Ihre Abhängigkeiten als Argumente akzeptieren:

public void Validate(HttpContext context)
{
    ValidatePath(context.Server.MapPath("App_Data/ErrorCodes.xml"));
}

public void ValidatePath(string path)
{
    XDocument xdoc = XDocument.Load(path);
    ValidateDocument(xdoc);
}

public void ValidateDocument(XDocument xdoc)
{
    // Original code
}

Sie können dann die verschiedenen Methoden unabhängig voneinander testen. Testen Sie zum Beispiel, wie ValidatePath() behandelt eine fehlende Datei.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X