我试图为一些SQL server存储过程和函数编写一些集成测试。我希望有一个数据库,其中包含一组已知的测试数据,然后将每个测试包装在一个事务中,并在完成时将其回滚,这样测试实际上是独立的。
存储过程/函数可以执行任何操作,从相当简单的联接查询到带有多层联接的复杂筛选,到插入数据到多个表。
有几个存储过程实际上使用事务,因此这些存储过程很难测试。我将展示执行的整个代码的示例,但请记住,这通常是在两个不同的位置(测试设置/拆卸和实际存储过程)。对于这个示例,我还使用了一个非常简单的临时表:
CREATE TABLE #test (
val nvarchar(500)
)示例:
-- 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)。此外,第二次回滚会导致错误,尽管可以通过以下方法避免这一点:
-- begin of test teardown --
if @@trancount > 0
begin
rollback transaction
end
go
-- end of test teardown它并没有解决真正的问题:在“示例选择#2",我们仍然在表中得到"cccc”--它不再回滚,因为没有事务活动。
有办法绕道吗?对于这种类型的测试是否有更好的策略?
注意:我不确定代码库在回滚后是否做过任何事情(插入'cccc‘部分) --但是如果它曾经做过,无论是有意的还是偶然的,测试都有可能以奇怪的方式中断,因为意外的数据可以从另一个测试中遗留下来。
有点类似于包含尝试捕获回滚模式的嵌套存储过程?,但这里提出的问题没有真正的解决方案。
发布于 2010-02-22 19:32:15
代码中的回滚不嵌套。它们将所有内容回滚到第一个开始事务。
但是,对于每个BEGIN事务,@@trancount会增加一个,但是,任何回滚集@@trancount都会返回到零。
如果要回滚事务的一部分,则需要使用事务保存点。你可以在BOL里查他们,得到比我能进入的更多的信息。
http://msdn.microsoft.com/en-us/library/ms188378.aspx
发布于 2010-02-22 19:38:28
我希望有一个数据库,其中包含一组已知的测试数据,然后将每个测试包装在一个事务中,并在完成时将其回滚,这样测试实际上是独立的。
不要。首先,您不会实际测试该功能,因为在现实世界中,过程将提交。第二,这是更重要的,您将得到一个凉亭错误失败,并需要实现解决方案来读取脏数据,因为您实际上没有提交,而且您不能做任何适当的验证。
相反,使用熟悉的集合进行数据库备份,然后在测试之前快速恢复它。将测试分组到可以在新的数据库恢复上运行的套件中,而不会相互影响,因此可以减少所需的还原次数。
您还可以使用数据库快照,获取套件启动时的快照,然后在每次测试之前从快照中还原数据库,请参阅如何:将数据库还原为数据库快照(Transact-SQL)。
或者组合这两种方法:套件设置(即。(单元测试@class方法)从.bak文件中恢复数据库并创建快照,然后每个测试从快照恢复数据库。
发布于 2010-03-10 19:40:22
我对这种设置也有类似的问题,我的想法是创建一个"SetupTest“脚本和一个"ClearTest”脚本,以便在测试执行之前和之后运行。除非您在这里讨论大量的数据--这会使测试执行过于缓慢,否则这应该运行良好,并使测试可重复,因为您知道,每次运行该测试套件时,都会有正确的数据等待执行。
https://stackoverflow.com/questions/2313525
复制相似问题