为模拟单元测试提供数据

时间:2014-02-03 15:33:14

标签: delphi unit-testing mocking spring4d

我正在进行单元测试的类滚动数据库表的每个记录,并将字段中的值与前一个值相加。以下是减少为骨骼的类:

procedure TSumList.Sum;
var
  FSum:integer;
begin
  FSum:=0;
  FDB.First;
  while not FDB.EOF do
  begin
    FSum:=FSum+FDB.GetAmount;
    FDB.Next;
  end;
end;

FDB是指名为IIDBTable的数据库模拟接口。

以下是依赖注入的DB模拟:

  IIDBTable = interface
    ['{A299D1D6-93AF-45CC-8DE2-9A4EE188C352}']
    procedure First;
    procedure Next;
    function EOF : boolean;
    function GetAmount:integer;
  end;

  TMockDBTable = class (TInterfacedObject,IDBTable)
    procedure First;
    procedure Next;
    function EOF : boolean;
    function GetAmount:integer;
  end;

问题是我不知道如何为模拟测试提供数据。当然我可以添加一个额外的程序,比如说AddValues(aAmount:整数),但是在这种情况下,我最终会在生产中使用这个额外的程序而且我不需要它。

最佳做法是什么?

我使用Spring for Delphi框架

2 个答案:

答案 0 :(得分:4)

您也可以使用DSharp模拟(或Delphi Mocks)。

这将是DSharp的设置代码(Delphi Mocks应该类似)

var
  mockDBTable: Mock<IIDBTable>;
begin
  mockDBTable.Setup.WillExecute.Once.WhenCalling.First;
  mockDBTable.Setup.WillReturn(False).Exactly(5).WhenCalling.EOF;
  mockDBTable.Setup.WillReturn(True).Once.WhenCalling.EOF;
  mockDBTable.Setup.WillReturn(5).Once.WhenCalling.GetAmount;
  mockDBTable.Setup.WillReturn(4).Once.WhenCalling.GetAmount;
  mockDBTable.Setup.WillReturn(3).Once.WhenCalling.GetAmount;
  mockDBTable.Setup.WillReturn(2).Once.WhenCalling.GetAmount;
  mockDBTable.Setup.WillReturn(1).Once.WhenCalling.GetAmount;
  mockDBTable.Setup.WillExecute.Exactly(5).WhenCalling.Next;

您在此处执行的操作是指定您希望调用的内容以及要返回的内容。 这样可以避免手动编写模拟类并使用数据提供它。

答案 1 :(得分:2)

为模拟类AddValues添加一个额外的方法。它只存在于那个模拟类中,而不存在于真正的类中,所以你反对额外的代码会出现在生产中是没有根据的。

我怀疑你认为代码需要在生产中,因为你只是通过接口处理模拟对象。额外的方法将存在于接口中,因此需要在类的生产版本中实现,即使它不属于那里。

相反,实例化TMockDBTable并通过对象引用访问它以设置它,但是测试需要它。准备就绪后,然后切换到通过IIDBTable界面使用它。

另一种选择是通过添加到构造函数的参数将数据提供给类。那么你甚至不需要额外的方法,因此没有诱惑在接口或生产类上定义该方法。没有理由你的mock类的构造函数需要看起来像生产类的构造函数,因为类根本不相关。构造函数不是接口定义的一部分。

相关问题