CheckException accetta solo metodi con 0 parametri;come posso verificare che altri metodi lancino eccezioni?

StackOverflow https://stackoverflow.com/questions/4613152

Domanda

Mi chiedo quale sia la procedura migliore per verificare le eccezioni in dunit.Non ho molta familiarità con i puntatori di metodo in Delphi.Esiste la possibilità di associare argomenti a un puntatore al metodo in modo che possa essere invocato senza argomenti.Al momento scrivo sempre un metodo aggiuntivo che esegue manualmente questo "associazione".Questo sarà fastidioso se il SUT ha molti metodi di lancio.

// What i did before i knew abput CheckExcepion
procedure MyTest.MyMethod_BadInput_Throws;
var
    res: Boolean;
begin
    res := false;
    try
        sut.MyMethod('this is bad');
    except
        on e : MyExpectedException do:
            res := true;
    end;
    CheckTrue(res);
end;

// What i do now
procedure MyTest.MyMethodWithBadInput;
begin
    sut.MyMethod('this is bad');
end;

procedure MyTest.MyMethod_BadInput_Throws;
begin
    CheckException(MyMethodWithBadInput, MyExpectedException);
end;

// this would be nice
procedure MyTest.MyMethod_BadInput_Throws;
begin
    CheckException(
        BindArguments(sut.MyMethod, 'this is bad'),  // <-- how to do this
        MyExpectedException);
end;
È stato utile?

Soluzione

È possibile utilizzare StartExpectingException per circondare il vostro il vostro chiamata al metodo).

StartExpectingException(MyException);
MyMethod(MyParam);
StopExpectingException();

Altri suggerimenti

Non so se dunit sostiene ancora, ma questo è un caso d'uso perfetto per i metodi anonimi, che sono stati introdotti in Delphi 2010. Se dunit non supporta allora si può facilmente modificare il sorgente da soli.

Come ha fatto notare, questo è un luogo ideale per i metodi anonimi.

Ecco come lo faccio. I "preso in prestito" da questo Alex Ciobanu:

procedure TestTMyClass.CheckException(aExceptionType: TClassOfException; aCode: TTestCode; const aMessage: String);
var
  WasException: Boolean;
begin
  WasException := False;
  try
    aCode;
  except
    on E: Exception do
    begin
      if E is aExceptionType then
      begin
        WasException := True;
      end;
    end;
  end;
  Check(WasException, aMessage);
end;

Poi lo chiamano con qualcosa di simile:

CheckException(ETestingException, 
             procedure begin FMyClass.RaiseTestingException end,      
             'The ETestingException exception didn''t get raised.  That is impossible!');

Per l'uso StartExpectingException() non è il modo migliore nel caso in cui si desidera testare più di un caso di eccezione. Al fine di testare tutti i casi possibili nella mia procedura di prova, insieme con le eccezioni che uso questo algoritmo:

uses
  Dialogs;
procedure MyTest.MyMethod_Test;
begin
  // Test for Exceptions
  try
    MyMethod(MyParam1CreatingException1);
    ShowMessage('Error! There should have been exception: Exxx here!');
    Check(false);
  except on E: Exception do Check(E is  ExceptionType1); end; // This exception is OK
  try
    MyMethod(MyParam2CreatingException2);
    ShowMessage('Error! There should have been exception: Exxx here!');
    Check(false);
  except on E: Exception do Check(E is  ExceptionType2); end; // This exception is OK
  // ... test other exceptions ...

  // Test other parameters
  CheckEquals('result1', MyMethod(MyParam1));
  CheckEquals('result2', MyMethod(MyParam2));
  // ... other tests ...
end;

Il motivo per cui io uso ShowMessage('Error! There should be exception: Exxx here!'); invece del metodo Check(false, 'There should have been an EListError.'); fornita è che nel mio caso (Delphi6) il Check(boolean, 'Message') non funziona - non mostra il messaggio nel caso in cui Check è blocco try...except all'interno (non so perché).

Questa è la versione funzionante e migliorata della risposta di Nick Hodges, che sottoclassa quella di DUnit TestFramework.TTestCase:

uses
  TestFramework, System.SysUtils;
type
  TTestCode = reference to procedure;

  TTestCasePlus = class(TestFramework.TTestCase)
    procedure CheckException(
      ExceptionType: TClass; Code: TTestCode; const Message: String = '');
  end;

implementation

procedure TTestCasePlus.CheckException(
  ExceptionType: TClass; Code: TTestCode; const Message: String = '');
{ Check whether some code raises a specific exception type.

Adapted from http://stackoverflow.com/a/5615560/797744

Example:

  Self.CheckException(EConvertError,
                      procedure begin UnformatTimestamp('invalidstr') end);

@param ExceptionType: The exception class which we check if it was raised.
@param Code: Code in the form of an anonymous method that should raise the
  exception.
@param Message: Output message on check failure. }
var
  WasRaised: Boolean;
begin
  WasRaised := False;
  try
    Code;
  except
    on E: Exception do
      if E is ExceptionType then
        WasRaised := True;
  end;
  Check(WasRaised, Message);
end;

Un bel vantaggio per questo metodo di verifica se è stata sollevata un'eccezione Start/StopExpectingException() è che puoi eseguire il testrunner nella build di debug e non continuerà a disturbarti con "È stata sollevata un'eccezione.Rottura?Continuare?" ogni volta che viene sollevata un'eccezione, anche se è stata gestita.

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