【发布时间】:2010-03-11 03:40:22
【问题描述】:
我正在尝试为一些 SQL 服务器存储过程和函数编写一些集成测试。我想要一个数据库,其中包含一组已知的测试数据,然后将每个测试包装在一个事务中,完成后将其回滚,以便测试有效地独立。
存储过程/函数可以做任何事情,从相当简单的连接查询到具有多层连接的复杂过滤,再到将数据插入多个表。
有几个实际使用事务的存储过程 - 因此这些更难测试。我将展示一个执行的整体代码示例,但请记住,这通常位于两个不同的位置(测试设置/拆卸和实际的存储过程)。对于这个示例,我还使用了一个非常简单的临时表:
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
这里的问题是,在“Example select #1”处,我希望“aaaa”和“cccc”在表中,但实际上只有“cccc”在表中,因为 SQL Server 实际上回滚了 ALL交易(见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
它并没有解决真正的问题:在“Example select #2”处,我们仍然在表中得到“cccc”——它不再被回滚,因为没有事务处于活动状态。
有没有办法解决这个问题?这种类型的测试有更好的策略吗?
注意:我不确定代码库在回滚后是否做过任何事情(插入“cccc”部分)——但如果它做过,无论是有意还是无意,测试可能会中断以奇怪的方式,因为意外数据可能会从另一个测试中遗留下来。
有点类似于Nested stored procedures containing TRY CATCH ROLLBACK pattern?,但这里提出的问题没有真正的解决方案。
【问题讨论】:
标签: sql-server unit-testing integration-testing