【问题标题】:Testing a stored procedure that operates on a caller's temp table测试在调用者的临时表上运行的存储过程
【发布时间】:2017-04-04 07:25:48
【问题描述】:

我一直在尽力遵循http://www.sommarskog.se/share_data.html 和 tSQLt 文档中的智慧;试图保持我的存储过程轻巧且相对不复杂,以便它们易于测试。因此,我发现自己在主存储过程中创建了一个临时表,然后在从主存储过程调用的“辅助”存储过程中对该临时表进行操作。这很好用,但测试起来有点尴尬。

单独测试“辅助”存储过程时,临时表必须已经存在。看起来在[Set Up] 过程中创建临时表不会持续到单元测试,但创建一个完整的表可以。

因此,为了避免在每个单元测试中重复 CREATE TABLE #temp(及其完整的列定义),我正在做以下变体:

EXEC tSQLt.NewTestClass 'SEtest';
GO

CREATE PROCEDURE [SEtest].[SetUp]
AS
BEGIN
  CREATE TABLE SEtest.temptemplate (col1 int);
END;
GO

CREATE PROCEDURE [SEtest].[test example]
AS
BEGIN
  -- Assemble
  SELECT TOP (0) * INTO #temp FROM SEtest.temptemplate;
  INSERT INTO #temp (col1)
  VALUES (1),(2),(5),(7);

  -- Act
  EXEC dbo.REMOVE_EVEN_NUMBERS;

  -- Assert
  SELECT TOP (0) * INTO #expected FROM #temp;
  INSERT INTO #expected (col1)
  VALUES (1),(5),(7);

  EXEC tSQLt.AssertEqualsTable '#expected', '#temp';
END;
GO

有没有更好的方法来协调 tSQLt 与通过临时表在存储过程之间共享数据?

【问题讨论】:

  • “我发现自己在主存储过程中创建了一个临时表,然后在从主存储过程调用的“辅助”存储过程中对该临时表进行操作”——我在任何地方都避免使用这种模式可能的。一旦实现从存储过程中“泄漏”出来,维护和测试就会变得更加困难。内联表值函数通常是一种解决方案
  • 米奇,我不同意。在这种情况下,#temp 表的定义是存储过程和调用者之间契约的一部分。因此,如果您有正确的测试,它不会使程序更难维护。但是,我同意它有点丑(但有时 T-SQL 很丑)。
  • 我唯一能想到的可能是改进的方法是一个进程键控的永久表。只要我不介意不驻留在 tempdb 中并且在数据库中有一个额外的对象对性能的轻微影响,我可能可以像往常一样在测试中使用 FakeTable 它。

标签: sql-server unit-testing stored-procedures tsqlt


【解决方案1】:

真的没有更好的办法了。

使用 #temp 表作为表值参数引用在 T-SQL 中本质上是丑陋的,并且也会导致测试中的丑陋。但是,您的测试似乎经过深思熟虑,应该能提供您正在寻找的东西。

我建议对您的模式进行的唯一改进是在测试模式中永久创建 SEtest.temptemplate 表,而不是在每次测试运行时即时重新创建它。

使用SELECT ... INTO 创建特定于测试的表是我在测试中到处使用的模式。而且由于您无法在子过程中创建临时表,因此这是我们唯一的干净选项。

无论哪种方式,都不要在测试中使用CREATE TABLE 语句来创建#temp 表,因为如果表架构发生变化,这将成为维护的噩梦。


更新:

您可能需要考虑一种替代方案。由于您的 #temp 表基本上是一个表值参数,因此使用表类型并不是一个坏主意。现在,这仍然很笨拙,但它提高了各个方面的可维护性:

DECLARE @template AS dbo.tabletype;
SELECT * INTO #temptable FROM @template;

这使得可读性更加清晰,特别是如果您的表类型的名称具有表达性(并且它与所讨论的过程在同一架构中)。

有了这个,您可以在任何调用过程中使用相同的模式,而不仅仅是在测试中。这也使实际代码更加明显/可读,并且在表定义发生变化时减少了维护工作。

【讨论】:

  • 更新添加了一个额外的想法,使代码更加明显。
猜你喜欢
  • 1970-01-01
  • 2016-08-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多