1

我一直在尽力遵循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 与通过临时表在存储过程之间共享数据?

4

1 回答 1

3

真的没有更好的办法了。

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

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

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

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


更新:

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

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

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

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

于 2016-11-21T01:42:51.190 回答