我正在进行单元测试的类滚动数据库表的每个记录,并将字段中的值与前一个值相加。以下是减少为骨骼的类:
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框架
答案 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类的构造函数需要看起来像生产类的构造函数,因为类根本不相关。构造函数不是接口定义的一部分。