Checkexception يقبل فقط طرق المعلمة ؛ كيف أختبر أن الأساليب الأخرى ترمي الاستثناءات؟

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

سؤال

أتساءل ما هي أفضل ممارسة لاختبار الاستثناءات في Dunit. أنا لست على دراية بمؤشرات الطريقة في دلفي. هل هناك أي إمكانية لربط وسيطات بمؤشر الطريقة بحيث يمكن استدعاؤها بدون حجج. في الوقت الحالي ، أكتب دائمًا طريقة إضافية تقوم بهذا "الربط" يدويًا. سيكون هذا مزعجًا إذا كان لدى 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 يدعمه حتى الآن ، ولكن هذه حالة استخدام مثالية للطرق المجهولة التي تم تقديمها في Delphi 2010. إذا لم يدعمها Dunit ، فيمكنك تعديل المصدر بنفسك بسهولة.

كما لوحظ ، هذا مكان رائع للطرق المجهولة.

إليكم كيف أفعل ذلك. لقد "استعارت" هذا من أليكس سيوبانو:

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() ليست هي أفضل طريقة في حال تريد اختبار المزيد من حالات استثناء واحدة. من أجل اختبار جميع الحالات الممكنة في إجراء الاختبار الخاص بي ، إلى جانب استثناءات أستخدم هذه الخوارزمية:

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 كتلة (لا تعرف لماذا).

هذه هي النسخة العاملة والمحسّنة من إجابة نيك هودجز ، والتي 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() هل يمكنك تشغيل testrunner في بناء التصحيح ولن يستمر في إزعاجك "استثناء تم رفعه. استراحة؟ تابع؟" في كل مرة يتم فيها إثارة استثناء-على الرغم من أنه تم التعامل معه.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top