CheckExceptionは0・パラメータ法を受け入れます。どのように私は他の方法が例外をスローテストするのですか?
-
26-09-2019 - |
質問
私はDUnitので例外をテストするためのベストプラクティス何思ったんだけど。私は、Delphiでのメソッドポインタに精通していないです。それは引数なしで実行することができるようにメソッドポインタにバインド引数のいずれかの可能性があります。現時点では私はいつもこの手で「結合」し、追加の方法を記述します。 SUTは、メソッドを投げるの多くを持っている場合、これは厄介なことになるだろう。
// 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;
解決
あなたが)あなたのあなたのメソッド呼び出しを囲むようにStartExpectingException
を使用することができます。
StartExpectingException(MyException);
MyMethod(MyParam);
StopExpectingException();
他のヒント
のDUnitはまだそれをサポートしているかどうかは知りませんが、これはDUnitのがそれをサポートしていない場合、あなたは簡単にソースを自分で変更することができますデルファイ2010年に導入された匿名メソッドのための完璧なユースケースです。
のように、これは匿名メソッドのための絶好の場所です、注意します。
ここで私はそれを行う方法です。私はアレックス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;
次にようなものでそれを呼び出します
CheckException(ETestingException,
procedure begin FMyClass.RaiseTestingException end,
'The ETestingException exception didn''t get raised. That is impossible!');
使用するにStartExpectingException()
は、あなたがより多く、テストに1例外のケースをしたい場合には最良の方法ではありません。例外と一緒に、私のテスト手順のすべての可能なケースをテストするために、私は、このアルゴリズムを使用します:
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;
は、私が代わりに提供さShowMessage('Error! There should be exception: Exxx here!');
方法のCheck(false, 'There should have been an EListError.');
を使用する理由は、私の場合(Delphi6)にCheck(boolean, 'Message')
は仕事をしないということである - それはチェックが内部try...except
ブロック(理由は分からない)である場合にはメッセージは表示されません。
これはニック・ホッジス答えの作業と改良版、サブクラスの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;
例外がStart/StopExpectingException()
の上に上げられたかどうかをチェックする。この方法に素敵なボーナスを使用すると、デバッグビルドでテストランナーを実行することができ、それが「例外が発生した。ブレーク?続けますか?」とあなたを悩ませて保持しないということです例外が発生するたびに - 。それが処理されたにもかかわらず、