【问题标题】:Delphi Mocks lifecycle in DUnitDelphi 在 DUnit 中模拟生命周期
【发布时间】:2023-03-15 10:15:01
【问题描述】:

我想测试最简单的情况:测试模拟策略对象。 (查看:策略模式)。

如果我在TTestCase.setUp 方法中创建TMock<T> 并将其存储在TTestCase 实例属性中,那么我应该在tearDown 方法中释放/NIL 模拟变量吗?

mock := NIL 无法编译:

[dcc32 错误] TestUnit2.pas(44): E2010 不兼容的类型:'Delphi.Mocks.TMock' 和 'Pointer'。

mock.free 运行时没有任何错误,但我不确定是否应该调用它。当进程退出其作用域(在测试用例析构函数之后)时释放的模拟。

我应该调用/设置什么吗?

代码:

Unit2.pas:

unit Unit2;

interface

type
  TPartClass = class
  public
    function foo( x_ : integer ) : integer; virtual;
  end;

  TMainClass = class
  private
    fPart : TPartClass;
  public
    constructor create( part_ : TPartClass );

    function bar( x_ : integer ) : integer;
  end;

implementation

function TPartClass.foo( x_ : integer ) : integer;
begin
  result := x_ shl 1;
end;

constructor TMainClass.create( part_ : TPartClass );
begin
  inherited create;
  fPart := part_;
end;

function TMainClass.bar( x_ : integer ) : integer;
begin
  result := fPart.foo( x_ );
end;

TestUnit2.pas:

unit TestUnit2;

interface

uses
  Delphi.Mocks, TestFramework, Unit2;

type
  TTestTMainClass = class(TTestCase)
  strict private
    fPartClass : TMock<TPartClass>;
    FMainClass: TMainClass;
  public
    procedure SetUp; override;
    procedure TearDown; override;
  published
    procedure Testbar;
  end;

implementation

procedure TTestTMainClass.SetUp;
begin
  fPartClass := TMock<TPartClass>.create;
  FMainClass := TMainClass.Create( fPartClass );
end;

procedure TTestTMainClass.TearDown;
begin
  FMainClass.Free;
  FMainClass := NIL;
  //fPartClass.Free;
  //fPartClass := NIL;
end;

procedure TTestTMainClass.Testbar;
var
  ReturnValue: Integer;
  x_: Integer;
begin
  fPartClass.Setup.WillReturn( 10 ).When.foo( 5 );
  x_ := 5;
  ReturnValue := FMainClass.bar(x_);
  checkTRUE( returnValue = 10 );
end;

【问题讨论】:

    标签: delphi dunit delphi-mocks


    【解决方案1】:

    您应该始终清理在安装期间创建的 TearDown 中的所有内容。尽管事情可能会在以后清理,但这是一种很好的做法,并且可以让您在单元测试时查找资源泄漏。

    由于TMock&lt;T&gt; 是内部保存接口的记录,因此您需要确保在测试运行后清理这些接口,尽管它们可能会被下一次设置或测试用例实例销毁时覆盖。

    这就是 .Free 的用途(尽管源代码中有注释)

    一旦你用模拟做更复杂的事情,这一点就更重要了,因为它可能使事情保持活力或在测试后指向无效的引用。我在测试应用程序结束时看到了一些严重的崩溃,这些应用程序没有清理它们的模拟。

    【讨论】:

    • 好的。我希望我应该这样做。如果对象 A 创建对象 B,那么它应该处置它。我将再次取消对 mock.free 的注释。但是如何在释放后将其设置为 NIL 呢?编译器无法解释它。感谢您的快速答复。混淆解释:我阅读了您关于在未命名函数中创建并传递回自动发布的模拟的评论(在我发布我的问题之前)。 (我再也找不到它了)。我很困惑。也许 TestCase 实例范围会以同样的方式处理它。
    • 我又找到了:stackoverflow.com/questions/27874168/…这两种情况有什么区别? (他和我的)
    • 模拟的范围。它是另一个问题中的局部变量,因此超出了导致最终确定的范围(将内部接口设置为 nil 会导致这些接口后面的对象被破坏)。 Yours 是测试用例实例中的一个字段,只要该实例存在,它就会存在。
    • 好的。我模拟类实例而不是接口!并且只是自动发布的超出范围的接口。我终于明白了! :) 那么在 mock.free 之后的 mock := NIL 呢?我无法以编译器接受它的方式转换它。
    • @TheBitman TMock 是一个记录,而不是一个TMock 实例不是动态分配的,因此没有指向 nil 的指针。该记录有一个Free 方法来清理其数据字段。这就是你所需要的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-21
    • 2023-03-09
    • 1970-01-01
    • 2018-05-08
    相关资源
    最近更新 更多