单元测试和存储过程
Posted
技术标签:
【中文标题】单元测试和存储过程【英文标题】:Unit Testing and Stored Procedures 【发布时间】:2010-11-10 17:28:59 【问题描述】:如何对使用存储过程调用的代码进行单元测试?
在我的应用程序中,我使用了大量的单元测试 (NUnit)。对于我的 DAL,我使用 DevExpress XPO ORM。 XPO 的一个好处是它允许您使用内存中的数据存储。这使我可以在我的测试装置中设置测试数据,而无需外部依赖于数据库。
然后,随之而来的是优化!对于我们应用程序的某些部分,我们不得不求助于将通过 ORM 操作数据的代码替换为调用 T-SQL 存储过程。这当然会通过添加一个新的外部依赖来破坏我们漂亮的可测试代码。我们不能仅仅“模拟”存储过程调用,因为我们正在测试数据操作的副作用。
我已经计划最终用 LINQ to SQL 取代我对 XPO 的使用; LINQ to SQL 似乎允许我比 XPO 更好的查询能力,消除了对一些存储过程的需要。我希望如果我切换到 LINQ to SQL,我将能够让我的单元测试使用 LINQ to Objects 来避免数据库依赖。但是,我怀疑所有的 spoc 都可以用 LINQ to SQL 代替。
我应该:
咬紧牙关,更改我的一些测试装置,以便它们创建 SQL Server 数据库, 创建数据库单元测试而不是测试代码, 还是因为不值得而跳过测试这些孤立的事件?我也很想听听您的替代设置,其中存储过程与您的可测试代码和平共存。
【问题讨论】:
【参考方案1】:我为此使用的方法是将调用存储过程的逻辑层封装在另一个方法或类后面。然后,您可以将数据库层逻辑与应用程序逻辑的测试分开测试。这样,您可以为客户端应用程序逻辑创建单独的单元测试,并为服务器端(数据库)应用程序逻辑创建集成测试。给定一段使用存储过程调用的代码,如下所示:
class foo:
prop1 = 5
def method1(listOfData):
for item in listOfData:
dbobj.callprocedure('someprocedure',item+prop1)
可以重构,将对远程系统的调用封装到自己的方法中:
class foo:
prop1 = 5
def method1(listOfData):
for item in listOfData:
someprocedure(item+prop1)
def someprocedure(value):
dbobj.callprocedure('someprocedure',value)
现在,当您编写单元测试时,模拟出 someprocedure() 类方法,这样它就不会实际调用数据库。然后创建一组单独的集成测试,这些测试需要配置的数据库调用 someprocedure() 的实际版本,然后验证数据库是否处于正确状态。
【讨论】:
以上是关于单元测试和存储过程的主要内容,如果未能解决你的问题,请参考以下文章