首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >单元测试存储过程时嵌套事务的回滚

单元测试存储过程时嵌套事务的回滚
EN

Stack Overflow用户
提问于 2010-02-22 19:28:48
回答 3查看 2.5K关注 0票数 0

我试图为一些SQL server存储过程和函数编写一些集成测试。我希望有一个数据库,其中包含一组已知的测试数据,然后将每个测试包装在一个事务中,并在完成时将其回滚,这样测试实际上是独立的。

存储过程/函数可以执行任何操作,从相当简单的联接查询到带有多层联接的复杂筛选,到插入数据到多个表。

有几个存储过程实际上使用事务,因此这些存储过程很难测试。我将展示执行的整个代码的示例,但请记住,这通常是在两个不同的位置(测试设置/拆卸和实际存储过程)。对于这个示例,我还使用了一个非常简单的临时表:

代码语言:javascript
运行
复制
CREATE TABLE #test (
  val nvarchar(500)
)

示例:

代码语言:javascript
运行
复制
-- for this example, just ensuring that the table is empty
delete from #test
go


-- begin of test setup code --
begin transaction 
go
-- end of test setup code --

    -- begin of code under test --
    insert into #test values('aaaa')

    begin transaction 
    go

        insert into #test values('bbbbb')

    rollback transaction 
    go

    insert into #test values('ccccc')

    -- Example select #1:
    select * from #test

    -- end of code under test --

-- begin of test teardown --
rollback transaction 
go
-- end of test teardown

-- checking that #temp is still empty, like it was before test  
-- Example select #2:
select * from #test

这里的问题是,在“示例选择#1”时,我希望"aaaa“和"cccc”在表中,但实际上只有"cccc“在表中,因为Server实际上回滚了所有事务(请参阅http://abdulaleemkhan.blogspot.com/2006/07/nested-t-sql-transactions.html)。此外,第二次回滚会导致错误,尽管可以通过以下方法避免这一点:

代码语言:javascript
运行
复制
-- begin of test teardown --
if @@trancount > 0 
begin
    rollback transaction 
end
go
-- end of test teardown

它并没有解决真正的问题:在“示例选择#2",我们仍然在表中得到"cccc”--它不再回滚,因为没有事务活动。

有办法绕道吗?对于这种类型的测试是否有更好的策略?

注意:我不确定代码库在回滚后是否做过任何事情(插入'cccc‘部分) --但是如果它曾经做过,无论是有意的还是偶然的,测试都有可能以奇怪的方式中断,因为意外的数据可以从另一个测试中遗留下来。

有点类似于包含尝试捕获回滚模式的嵌套存储过程?,但这里提出的问题没有真正的解决方案。

EN

Stack Overflow用户

发布于 2010-02-22 19:38:28

我希望有一个数据库,其中包含一组已知的测试数据,然后将每个测试包装在一个事务中,并在完成时将其回滚,这样测试实际上是独立的。

不要。首先,您不会实际测试该功能,因为在现实世界中,过程将提交。第二,这是更重要的,您将得到一个凉亭错误失败,并需要实现解决方案来读取脏数据,因为您实际上没有提交,而且您不能做任何适当的验证。

相反,使用熟悉的集合进行数据库备份,然后在测试之前快速恢复它。将测试分组到可以在新的数据库恢复上运行的套件中,而不会相互影响,因此可以减少所需的还原次数。

您还可以使用数据库快照,获取套件启动时的快照,然后在每次测试之前从快照中还原数据库,请参阅如何:将数据库还原为数据库快照(Transact-SQL)

或者组合这两种方法:套件设置(即。(单元测试@class方法)从.bak文件中恢复数据库并创建快照,然后每个测试从快照恢复数据库。

票数 1
EN
查看全部 3 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2313525

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档