Domanda

Ho una classe in cui sto testando l'unità con DUnit. Ha una serie di metodi alcuni metodi pubblici e metodi privati.

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

Per scrivere un test unitario per questa classe, devo rendere pubblici tutti i metodi.

Esiste un modo diverso di dichiarare i metodi privati ??in modo che io possa ancora testarli ma non sono pubblici?

È stato utile?

Soluzione

Non è necessario renderli pubblici. Lo farà protetto. Quindi è possibile sottotipare la classe per unit test e presentare i metodi protetti. Esempio:

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

Ora puoi sottotiparlo per il tuo test unitario:

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;

Tuttavia, se i metodi che vuoi testare l'unità stanno facendo cose così intimamente con il modulo dati che non è sicuro averli tutt'altro che privati, allora dovresti davvero considerare il refactoring dei metodi al fine di separare il codice che necessita da testare unitamente e il codice che accede alle viscere del modulo dati.

Altri suggerimenti

È un po 'confuso, ma penso che questo sia l'approccio più semplice e chiaro. Utilizzare questa direttiva di compilazione condizionale:

  {$IfNDef TEST}
  private
  {$EndIf}

Il progetto di unit test deve definire TEST in progetto ? condizionale definisce . Senza una specifica di visibilità, vengono pubblicati.

Attenzione: se la visibilità privata non è la prima nella dichiarazione di classe, otterrà la definizione precedente. Un modo più sicuro, ma più dettagliato e meno chiaro, sarebbe:

  private
  {$IfDef TEST}
  public
  {$EndIf}

Ciò presenta molti vantaggi rispetto alla sottoclasse o ad altri approcci:

  • Nessuna complessità aggiuntiva: nessuna classe aggiuntiva nel tuo codice.
  • Nessuno può " erroneamente " sottoclasse e sovrascrivi la tua classe: preservi la tua architettura.
  • Quando dici che un metodo è protetto, ti aspetti in qualche modo che venga ignorato. Lo stai dicendo a chi sta leggendo il tuo codice. Un metodo protetto che non deve essere ignorato confonderà i tuoi lettori di codice, violando il mio primo principio di programmazione: " Il codice deve essere scritto per essere letto da altri esseri umani. & Quot;
  • DUnit è nella propria unità, non inclusa ovunque.
  • Non tocchi il disordinato RTTI.

Penso che sia una soluzione più chiara e migliore della risposta selezionata.

Quando lo uso, configuro anche il progetto di test per mettere gli oggetti di build in una diversa directory del progetto principale. Questo impedisce ai binari con la direttiva TEST di mescolarsi con l'altro codice.

Raccomando " XUnit Test Patterns " libro di Gerard Meszaros:

Sottoclasse specifica del test

  

Domanda : come possiamo creare il codice   testabile quando abbiamo bisogno di accedere   stato privato del SUT?

     

Rispondi : aggiungi metodi che espongono il   stato o comportamento richiesto dal test   in una sottoclasse del SUT.

     

... Se il sistema sotto test (SUT) non lo era   progettato specificamente per essere testabile,   potremmo scoprire che il test non può essere eseguito   accesso per dichiarare che deve   inizializzare o verificare a un certo punto   il test.

L'articolo spiega anche quando usarlo e quali rischi comporta.

Inserisci il codice DUnit nella tua unità. Puoi quindi accedere a tutto ciò che ti piace.

In generale, quando mi trovo in questa situazione, spesso mi rendo conto che sto violando il principio della responsabilità singola. Naturalmente non so nulla del tuo caso specifico, ma FORSE, che i metodi privati ??dovrebbero essere nella loro classe. Il TAuth avrebbe quindi un riferimento a questa nuova classe nella sua sezione privata.

Con RTTI esteso (Delphi 2010 e versioni successive), invocare metodi privati ??tramite RTTI è un'altra opzione. Questa soluzione è anche la risposta più votata in Come testare una classe che ha metodi privati, campi o classi interne?

{$IFNDEF UNITEST}
private
{$ENDIF}

Soluzione semplice, che a malapena è un hack. Ho spesso bisogno di testare metodi privati ??e questa tecnica aggiunge meno complicazioni possibili.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top