CheckException accepte uniquement les méthodes 0-paramètres; comment puis-je tester que d'autres méthodes jettent des exceptions?
-
26-09-2019 - |
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;
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