Frage

Ich habe eine Klasse, die ich Unit-Tests bin in mit DUnit. Es hat eine Reihe von Methoden, einige öffentlichen Methoden und privaten Methoden.

type
  TAuth = class(TDataModule)
  private
    procedure PrivateMethod;
  public
    procedure PublicMethod;
  end;

Um einen Unit-Test für diese Klasse zu schreiben, ich alle Methoden öffentlich machen.

Gibt es eine andere Möglichkeit, die privaten Methoden zu erklären, damit ich sie noch testen können, aber sie sind nicht öffentlich?

War es hilfreich?

Lösung

Sie brauchen nicht, um sie öffentlich zu machen. Geschützte tun. Dann können Sie die Klasse für Unit-Tests Subtyp und die geschützten Methoden Oberfläche. Beispiel:

type
  TAuth = class(TDataModule)
  protected
    procedure MethodIWantToUnitTest;
  public
    procedure PublicMethod;
  end;

Jetzt können Sie es für Ihr Gerät zu testen Subtyp:

interface

uses
  TestFramework, Classes, AuthDM;

type
  // Test methods for class TAuthDM
  TestAuthDM = class(TTestCase)
     // stuff
  end;

  TAuthDMTester = class(TAuthDM)
  public
    procedure MethodIWantToUnitTestMadePublic;
  end;

implementation

procedure TAuthDMTester.MethodIWantToUnitTestMadePublic;
begin
  MethodIWantToUnitTest;
end;

Wenn jedoch die Methoden, die Sie Unit-Test wollen Dinge tun, so eng mit dem Datenmodul, das es nicht sicher ist, sie aber privat etwas haben, dann sollten Sie wirklich in Betracht ziehen, die Methoden, um Refactoring den Code zu trennen, die benötigt sein Einheit getestet und der Code, der die Innereien des Datenmoduls zugreift.

Andere Tipps

Es ist ein wenig hacky, aber ich denke, das ist die einfachste und klarer Ansatz. Verwenden Sie diese bedingte Kompilierung Richtlinie:

  {$IfNDef TEST}
  private
  {$EndIf}

Ihr Unit-Test-Projekt muss TEST in project → conditional defines definieren. Ohne Sichtbarkeit Spezifikation, werden sie veröffentlicht wurde.

Achtung: wenn die private Sicht nicht die erste in der Klassendeklaration ist, wird es die vorherige Definition erhalten. Ein sicherer Weg, aber ausführliche und weniger klar wäre:

  private
  {$IfDef TEST}
  public
  {$EndIf}

Dies hat viele Vorteile gegenüber dem Subclassing oder anderen Ansätzen:

  • Keine zusätzliche Komplexität: keine zusätzlichen Klassen in Ihrem Code
  • .
  • Niemand kann „versehentlich“ Unterklasse und überschreiben Sie Ihre Klasse. Sie Ihre Architektur bewahren
  • Wenn Sie eine Methode sagen geschützt ist, erwarten Sie etwas, dass es außer Kraft gesetzt werden. Sie sagen dies für den Code liest. Eine geschützte Methode, die nicht außer Kraft gesetzt werden sollte, wird die Code-Leser, bricht mir die erste Programmier Prinzip verwechseln: „Kodex muss von anderen Menschen zu lesen geschrieben werden“
  • DUnit in ihrer eigenen Einheit ist, nicht überall enthalten.
  • Sie berühren nicht chaotisch RTTI.

Ich denke, es ist eine klarere Lösung, und besser als die gewählten Antwort.

Als ich das verwenden, habe ich auch das Testprojekt konfigurieren, dass die Build-Objekte in einem anderen Verzeichnis des Hauptprojekts zu setzen. Dies verhindert, dass die Binärdateien mit der TEST-Richtlinie mit dem anderen Code zu mischen.

Ich empfehle die " XUnit Testmuster " Buch von Gerard Meszaros:

Test spezifische Subklasse

  

Frage : Wie können wir Code machen   prüfbar, wenn wir zugreifen müssen   privat Zustand des SUT?

     

Antwort : Fügen Sie Methoden, die die belichten   Zustand oder Verhalten durch den Test erforderlich   zu einer Unterklasse der SUT.

     

... Wenn das System unter Test (SUT) nicht   speziell entwickelt, um prüfbare entworfen,   wir können feststellen, dass der Test nicht bekommen kann   Zugang zu behaupten, dass es muss   initialisieren oder zu einem bestimmten Zeitpunkt überprüft in   der Test.

Der Artikel erklärt auch, wenn es zu benutzen und welche Risiken es trägt.

Setzen Sie den DUnit Code innerhalb des Geräts. Sie können dann alles zugreifen Sie möchten.

In der Regel, wenn ich in diese Situation kommen, merke ich oft, dass ich die einzige Verantwortung Prinzip bin zu verletzen. Natürlich weiß ich nichts über Ihren speziellen Fall, aber vielleicht, sollen sicherstellen, dass private Methoden in ihrer eigenen Klasse sein. Die TAuth würde als einen Hinweis auf diese neue Klasse in es privaten Bereich ist.

Mit Erweiterte RTTI (Delphi 2010 und neuer) unter Berufung auf private Methoden über RTTI eine weitere Option. Diese Lösung ist auch die top-rated Antwort in Wie teste ich eine Klasse, die private Methoden hat, Felder oder innere Klassen?

{$IFNDEF UNITEST}
private
{$ENDIF}

Einfache Lösung, die kaum ein Hack ist. Ich brauche häufig private Methoden und diese Technik fügt so wenig Komplikationen wie möglich zu testen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top