2009-07-14 66 views
3

您如何对使用存储过程调用的代码进行单元测试?单元测试和存储过程

在我的应用程序中,我使用了很多单元测试(NUnit)。对于我的DAL,我使用DevExpress XPO ORM。 XPO的一个好处是它可以让你使用内存中的数据存储。这使我可以在我的测试夹具中设置测试数据,而不必依赖于数据库。

然后,沿着优化!对于我们应用程序的某些部分,我们不得不求助于将通过我们的ORM操纵数据的代码替换为调用T-SQL存储过程。当然,通过添加新的外部依赖关系打破了我们良好的可测试代码。我们不能只是“模拟”存储过程调用,因为我们正在测试数据操作的副作用。

我已经有计划最终用LINQ to SQL取代XPO的用法; LINQ to SQL似乎允许我比XPO更好地查询功能,从而消除了对某些存储过程的需求。我希望如果我切换到LINQ to SQL,我将能够让我的单元测试使用LINQ to Objects来避免数据库依赖。但是,我怀疑所有的spocs都可以被LINQ to SQL所取代。

我应该:

  • 硬着头皮改变我的一些测试夹具,使他们创建SQL Server数据库,
  • 创建数据库单元测试,而不是测试代码,
  • 或跳过测试这些孤立的事件,因为他们不值得吗?

我也很想听听有关存储过程和您的可测试代码和平共存的其他设置。

回答

2

我使用的方法是将存储过程调用的逻辑层封装在另一个方法或类的后面。然后,您可以测试与应用程序逻辑测试分开的数据库层逻辑。这样,您可以为客户端应用程序逻辑和服务器端(数据库)应用程序逻辑的集成测试创建单独的单元测试。给定一段代码,利用存储过程调用,因为我有如下:

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()类的方法,以便它实际上不会进行数据库调用。然后创建一组单独的集成测试,这些测试需要一个配置好的数据库,它调用某个过程的实际版本(),然后验证数据库是否处于正确的状态。