5
4

3 回答 3

4

AFAIK 这是TVirtualInterface标准类实现的限制,Delphi 模拟所依赖的。这是“新 RTTI”的弱点/限制之一。

唯一可能的解决方案是使用不使用此类的存根/模拟库TVirtualInterface

我所知道的唯一拥有自己的“虚拟类”工厂的库是我们的开源mORMot框架(适用于 Delphi 6 到 XE4,在 Win32 和 Win64 下)。它支持varout值参数。要测试任何输出参数值,您可以使用该ExpectsTrace()方法 - 这要归功于mORMot的出色“呼叫跟踪”功能

于 2013-08-16T13:40:10.877 回答
4

新的 delphi-mock 可以使用 reference-to-function-WillExecute 来做到这一点:

FUsers.Setup.WillExecute('CheckPwd',
  // function CheckPwd(UserId: integer; Pwd: string; out ErrorCode: Integer; out ErrorMsg: String) : Boolean;
  function (const args : TArray<TValue>; const ReturnType : TRttiType) : TValue
  var
     aErrorCode: Integer;
     aErrorMsg: String;
     aResult: Boolean
  begin
    // check against 5, as arg[0] is tkInterface and the method parameters start with arg[1]
    Assert.AreEqual(5, Length(args), 'wrong number of arguments passed to IDlUsers.CheckPwd(UserId: integer; Pwd: string; out ErrorCode: Integer; out ErrorMsg:String) : Boolean');

    Assert.IsTrue(args[1].IsType<integer>, 'wrong argument 1 type passed to IDlUsers.CheckPwd(UserId: integer; Pwd: string; out ErrorCode: Integer; out ErrorMsg:String) : Boolean');
    Assert.IsTrue(args[2].IsType<string>, 'wrong argument 2 type passed to IDlUsers.CheckPwd(UserId: integer; Pwd: string; out ErrorCode: Integer; out ErrorMsg:String) : Boolean');
    Assert.IsTrue(args[3].IsType<Integer>, 'wrong argument 3 type passed to IDlUsers.CheckPwd(UserId: integer; Pwd: string; out ErrorCode: Integer; out ErrorMsg:String) : Boolean');
    Assert.IsTrue(args[4].IsType<string>, 'wrong argument 4 type passed to IDlUsers.CheckPwd(UserId: integer; Pwd: string; out ErrorCode: Integer; out ErrorMsg:String) : Boolean');

    // ...

    arg[3] := TValue.From<Integer>(aErrorCode);
    arg[4] := TValue.From<string>(aErrorMsg);
    Result := TValue.From<Boolean>(aResult);
  end);

(我使用 Delphi XE7 和 DUnitX)

于 2015-09-07T12:15:22.013 回答
2

您使用的库不考虑通过引用传递的参数。它将所有参数视为要在调用模拟时匹配的输入值。此外,在调用模拟函数时,无法为这些参数分配新值。

另一种方法是更改​​函数的接口以使其可测试。您可以在失败时抛出异常。但是,异常并不适合此功能,因为未能输入正确的用户名和密码并不是异常事件。相反,请考虑返回错误代码。保留一个代码(通常为零)表示成功。

于 2013-08-16T12:20:19.257 回答