CheckException accepte uniquement les méthodes 0-paramètres; comment puis-je tester que d'autres méthodes jettent des exceptions?

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

Question

Je me demande quelle est la meilleure pratique pour tester des exceptions dans dunit. Je ne suis pas très familier avec les pointeurs de méthode dans Delphi. Y at-il possibilité de lier des arguments à un pointeur de méthode afin qu'il puisse être invoqué sans arguments. En ce moment je toujours écrire une méthode supplémentaire qui le fait « contraignant » manuellement. Cela va être gênant si le SUT a beaucoup de méthodes jeter.

// 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;
Était-ce utile?

La solution

Vous pouvez utiliser StartExpectingException pour entourer votre appel de méthode).

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

Autres conseils

Je ne sais pas si DUnit soutient encore, mais cela est un cas parfait d'utilisation pour les méthodes anonymes qui ont été introduites en Delphi 2010. Si DUnit ne le supporte pas, alors vous pouvez facilement modifier la source vous-même.

Comme indiqué, c'est un endroit idéal pour les méthodes anonymes.

Voici comment je le fais. I "emprunté" de ce 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;

Ensuite, appelez avec quelque chose comme:

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

Pour utiliser StartExpectingException() est pas la meilleure façon si vous voulez tester plus d'un cas d'exception. Afin de tester tous les cas possibles dans ma procédure de test, ainsi que des exceptions que j'utilise cet algorithme:

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;

La raison pour laquelle j'utilise ShowMessage('Error! There should be exception: Exxx here!'); au lieu de la méthode de Check(false, 'There should have been an EListError.'); fournie est que dans mon cas (Delphi6) le Check(boolean, 'Message') ne fonctionne pas - il ne montre pas le message en cas que l'enregistrement est à l'intérieur bloc try...except (ne sais pas pourquoi).

Ceci est la version de travail et l'amélioration de la réponse de Nick Hodges, qui sous-classes de la TestFramework.TTestCase de DUnit:

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 joli bonus à cette méthode de vérification si une exception a été soulevée sur Start/StopExpectingException() est que vous pouvez exécuter le TestRunner dans la version de débogage et il ne garderez pas vous embêter avec « exception a été soulevée. Briser? Continuer? » chaque fois qu'une exception est levée -. même si elle a été traitée

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top