请问tSQLt专家是否可以尝试测试一种不会返回任何内容但在表中执行字段更新的存储过程的方法?我了解如何从函数或SP测试结果返回,但是在就地更新的情况下,如何对照假表和实际表进行测试运行表名是硬编码的吗?我能想到的唯一方法是让整个SP使用动态SQL并将表名作为参数传递,但这会使代码更不易读,更脆弱。有没有更好的办法?下面是一个简单的存储过程,它查看另外两个字段:TransactionDate和ENdOfDropDate,并在同一个表中设置第三个字段,名为" IsWithinAddDrop"根据条件的结果判断为真还是假。
create table tblT1
(
ID [bigint] IDENTITY(1,1) NOT NULL,
TransactionDate [datetime2](7) NULL,
EndOfDropDate [datetime2](7) NULL,
IsWithinAddDrop [nvarchar](10) NULL
)
insert into tblT1 (TransactionDate, EndOfDropDate) values ('1/1/2016', '2/1/2016')
insert into tblT1 (TransactionDate, EndOfDropDate) values ('2/1/2016', '1/2/2016')
insert into tblT1 (TransactionDate, EndOfDropDate) values ('3/1/2016', '3/1/2016')
create procedure spUpdateIsWithinAddDrop
as
begin
Update t1
set t1.IsWithinAddDrop =
(case
when t1.TransactionDate <= t1.EndOfDropDate then 'True'
else 'False'
end)
from tblT1 t1
end
exec spUpdateIsWithinAddDrop
结果是我要测试的表中更新的列IsWithinAddDrop:
TransactionDate EndOfDropDate IsWithinAddDrop
2016-01-01 2016-02-01 True
2016-02-01 2016-01-02 False
2016-03-01 2016-03-01 True
谢谢!
答案 0 :(得分:2)
解决方案是首先模拟表以隔离任何依赖项(外键等)。然后添加足够的数据来测试您想要覆盖的所有案例(请参阅下面的示例中的注释)并使用tSQLt.AssertEqualsTable
将目标表的内容与运行下面的过程后的预定义的预期行集进行比较测试
if schema_id(N'StackModuleTests') is null
exec tSQLt.NewTestClass @ClassName = N'StackModuleTests'
go
if objectpropertyex(object_id(N'[StackModuleTests].[test spUpdateIsWithinAddDrop example]'), N'IsProcedure') = 1
drop procedure [StackModuleTests].[test spUpdateIsWithinAddDrop example]
go
create procedure [StackModuleTests].[test spUpdateIsWithinAddDrop example]
as
begin
--! Start by faking the table that will be updated to isolate this test from any other dependencies
exec tSQLt.FakeTable @TableName = 'dbo.tblT1' ;
--! We expect spUpdateIsWithinAddDrop to set IsWithinAddDrop to TRUE only if
--! TransactionDate is less than or equal to EndOfDropDate so we need the
--! following tests:
--!
--! Positive case where TransactionDate equals EndOfDropDate
--! Positive case where TransactionDate less than EndOfDropDate
--! Negative case where TransactionDate more than EndOfDropDate
--! May want other tests to cover scenarios where either column is null
--! Purists would say that this should one unit test for each case, personally
--! I feel that as SQL is a set based language it is OK to combine all cases
--! into a single test (also minimises all the setup)
--!
--! Assemble the data required for all test cases
insert into tblT1 (TransactionDate, EndOfDropDate)
values
('20160101', '20160101')
, ('20160101', '20160102')
, ('20160102', '20160101') ;
--! What do we expect to see afterwards?
create table #expected
(
TransactionDate [datetime2](7) null
, EndOfDropDate [datetime2](7) null
, IsWithinAddDrop [nvarchar](10) null
)
insert into #expected (TransactionDate, EndOfDropDate, IsWithinAddDrop)
values
('20160101', '20160101', 'True')
, ('20160101', '20160102', 'True')
, ('20160102', '20160101', 'False') ;
--! Act
exec dbo.spUpdateIsWithinAddDrop ;
--! Assert that the contents of tblT1 now match the #expected contents
--! Notice that we ignore the ID column completely in this test because
--! it has nothing to do with the object under test (spUpdateIsWithinAddDrop)
exec tSQLt.AssertEqualsTable @Expected = N'#expected', @Actual = N'tblT1' ;
end
go
exec tSQLt.Run '[StackModuleTests].[test spUpdateIsWithinAddDrop example]';
希望这能充分解释这种方法,但如果没有,请进一步澄清。