我试图为一些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:38:28
我希望有一个数据库,其中包含一组已知的测试数据,然后将每个测试包装在一个事务中,并在完成时将其回滚,这样测试实际上是独立的。
不要。首先,您不会实际测试该功能,因为在现实世界中,过程将提交。第二,这是更重要的,您将得到一个凉亭错误失败,并需要实现解决方案来读取脏数据,因为您实际上没有提交,而且您不能做任何适当的验证。
相反,使用熟悉的集合进行数据库备份,然后在测试之前快速恢复它。将测试分组到可以在新的数据库恢复上运行的套件中,而不会相互影响,因此可以减少所需的还原次数。
您还可以使用数据库快照,获取套件启动时的快照,然后在每次测试之前从快照中还原数据库,请参阅如何:将数据库还原为数据库快照(Transact-SQL)。
或者组合这两种方法:套件设置(即。(单元测试@class方法)从.bak文件中恢复数据库并创建快照,然后每个测试从快照恢复数据库。
https://stackoverflow.com/questions/2313525
复制相似问题