【问题标题】:Delphi Unit Testing : Writing a simple spy for the CUTDelphi 单元测试:为 CUT 编写一个简单的 spy
【发布时间】:2016-02-04 16:06:00
【问题描述】:

我正在寻找一种轻松简洁为 Delphi 下的 DUnitX 测试框架编写间谍程序的方法。

在过去,我使用了非常丑陋的方法:

[TestFixture]
Test = class(TObject)
public
  [test]
  procedure Test1;
end;

TMyClass = class(TObject)
protected
  procedure MyProcedure; virtual;
end;

TMyTestClass = class(TMyClass)
protected
  fMyProcedureCalled : Boolean;
  procedure MyProcedure; override;
end

procedure TMyTestClass.MyProcedure;
begin
   fMyProcedureCalled := true;
   inherited;
end;

procedure Test.Test1;
var aObj : TMyTestClass;
begin
   TMyTestClass.Create;
   Assert.IsTrue(aObj.fMyProcedureCalled);
end;

所有这些代码用于检查是否调用了一个过程。太啰嗦了!

有没有办法写一个间谍来帮助我减少代码?

【问题讨论】:

    标签: unit-testing delphi spy dunit dunitx


    【解决方案1】:

    听起来像是一个模拟的用例(我在这里使用术语模拟,因为大多数框架将它们的各种测试替身称为模拟)

    在以下示例中,我使用的是 DUnit,但它对 DUnitX 没有任何影响。我也在使用 Spring4D 1.2 的模拟功能(我没有检查 Delphi Mocks 是否支持这个)

    unit MyClass;
    
    interface
    
    type
      TMyClass = class
      private
        fCounter: Integer;
      protected
        procedure MyProcedure; virtual;
      public
        property Counter: Integer read fCounter;
      end;
    
    implementation
    
    procedure TMyClass.MyProcedure;
    begin
      Inc(fCounter);
    end;
    
    end.
    
    program Tests;
    
    uses
      TestFramework,
      TestInsight.DUnit,
      Spring.Mocking,
      MyClass in 'MyClass.pas';
    
    type
      TMyClass = class(MyClass.TMyClass)
      public
        // just to make it accessible for the test
        procedure MyProcedure; override;
      end;
    
      TMyTest = class(TTestCase)
      published
        procedure Test1;
      end;
    
    procedure TMyClass.MyProcedure;
    begin
      inherited;
    end;
    
    procedure TMyTest.Test1;
    var
      // the mock is getting auto initialized on its first use
      // and defaults to TMockBehavior.Dynamic which means it lets all calls happen
      m: Mock<TMyClass>;
      o: TMyClass;
    begin
      // set this to true to actually call the "real" method
      m.CallBase := True;
      // do something with o
      o := m;
      o.MyProcedure;
    
      // check if the expected call actually did happen
      m.Received(Times.Once).MyProcedure;
    
      // to prove that it actually did call the "real" method
      CheckEquals(1, o.Counter);
    end;
    
    begin
      RegisterTest(TMyTest.Suite);
      RunRegisteredTests();
    end.
    

    请记住,这仅适用于虚拟方法。

    【讨论】:

    • 如果您需要测试不受$RTTI 指令影响的基类中的方法,您可以使用一个小技巧并在public 部分的子类中将其重新定义为@987654324 @这将导致生成RTTI。
    • 感谢两位的回答。我不知道 Spring4d 有这个 Mocking 功能。确实很方便!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多