【问题标题】:Delphi DSharp Mock is throwing an Unexpected Invocation error - why?Delphi DSharp Mock 抛出意外调用错误 - 为什么?
【发布时间】:2021-09-13 01:48:54
【问题描述】:

在带有 DSharp Mock 的 Delphi DUnit 测试中使用记录类型作为接口时,它会抛出异常调用,但我不知道为什么?我在下面创建了测试控制台应用程序。

program ConsoleStuff;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  DSharp.Testing.Mock,
  DUnitTestRunner,
  Spring,
  TestFramework,
  System.SysUtils;

type

  {$M+}
  IMyType = interface
  ['{D3F69229-1B46-4FE2-B078-80AA313FB601}']
    function GetNullableSingle: Nullable<Single>;
    function GetSingleValue: Single;
    procedure SetNullableSingle(const Value: Nullable<Single>);
    procedure SetSingleValue(const Value: Single);
    property NullableSingle: Nullable<Single> read GetNullableSingle write SetNullableSingle;
    property SingleValue: Single read GetSingleValue write SetSingleValue;
  end;

  TMyType = class(TInterfacedObject, IMyType)
  private
    FNullableSingle: Nullable<Single>;
    FSingleValue: Single;
    function GetNullableSingle: Nullable<Single>;
    function GetSingleValue: Single;
    procedure SetNullableSingle(const Value: Nullable<Single>);
    procedure SetSingleValue(const Value: Single);
  public
    property NullableSingle: Nullable<Single> read GetNullableSingle write SetNullableSingle;
  end;

  TMyOtherType = class
  private
    FMyType: IMyType;
  public
    constructor Create(const AMyType: IMyType);
    procedure SetMyTypeValue(const AValue: Nullable<Single>);
  end;

  TMyOtherTypeTests = class( TTestCase)
  published
    procedure UnexpectedInvocation;
  end;

{ TMyType }

function TMyType.GetNullableSingle: Nullable<Single>;
begin
  Result := FNullableSingle;
end;

function TMyType.GetSingleValue: Single;
begin
  Result := FSingleValue;
end;

procedure TMyType.SetNullableSingle(const Value: Nullable<Single>);
begin
  FNullableSingle := Value;
end;

procedure TMyType.SetSingleValue(const Value: Single);
begin
  FSingleValue := Value;
end;

{ TMyOtherType }

constructor TMyOtherType.Create(const AMyType: IMyType);
begin
  FMyType := AMyType;
end;

procedure TMyOtherType.SetMyTypeValue(const AValue: Nullable<Single>);
begin
  FMyType.SetSingleValue(AValue.Value);  // This works OK
  FMyType.SetNullableSingle(AValue);     // This DOES NOT work
end;

{ TMyOtherTypeTests }

procedure TMyOtherTypeTests.UnexpectedInvocation;
var
  LMyOtherType: TMyOtherType;
  LMyType: Mock<IMyType>;
begin
  LMyType.Setup.WillExecute.Once.WhenCalling.SetSingleValue(Nullable<Single>.Create(10));      // This is OK
  LMyType.Setup.WillExecute.Once.WhenCalling.SetNullableSingle(Nullable<Single>.Create(10));   // This is NOT OK
  //LMyType.Setup.WillExecute.Once.WhenCallingWithAnyArguments.SetNullableSingle(Nullable<Single>.Create(10));   // This line WORKS OK
  LMyOtherType := TMyOtherType.Create(LMyType);
  LMyOtherType.SetMyTypeValue(Nullable<Single>.Create(10));
  LMyType.Verify;
end;

begin
  try
    RegisterTests('TMyOtherType', [TMyOtherTypeTests.Suite]);
    DUnitTestRunner.RunRegisteredTests;
    Readln;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

测试可以使用“WhenCallingWithAnyArguments”方法,但我确实需要“WhenCalling”方法来检查分配给属性设置器的值。

我将 Nullable 类型仅用于演示目的,其他 Record 类型也失败了。

请帮忙!

【问题讨论】:

    标签: delphi spring4d delphi-mocks


    【解决方案1】:

    DSharp Mocks 不支持所有类型的参数匹配(请参阅 DSharp.Core.Reflection 中的 SameValue)。

    您当然可以解决这个问题,但我建议您迁移到 Spring.Mocking,它的 API 略有不同,但提供了所有类型的参数匹配,并且功能更强大。

    【讨论】:

    • 感谢 Stefan 的快速回复。 Spring.Mocking 库上是否有任何文档?想检查一下,但需要一些帮助才能开始,并且示例项目似乎没有编译。
    • 所有用例都应该在Spring.Tests.Mocking.pas处理
    • 谢谢斯特凡!我已经离开 Delphi 几年了,不知道这个新的 Sping.Mocking 库的存在。很棒的工作,DSharp 更简单、更清洁。大赞!
    猜你喜欢
    • 2014-09-15
    • 1970-01-01
    • 1970-01-01
    • 2018-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-30
    相关资源
    最近更新 更多