2016-11-21 51 views
0

我一直在盡我所能去遵循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存儲過程之間的數據通過臨時表?

+0

「我發現自己在主存儲過程中創建臨時表,然後在從主存儲過程調用的」輔助「存儲過程中在該臨時表上進行操作」 - 我儘可能避免使用該模式。一旦存儲過程執行「泄漏」,維護和測試就變得更加困難。一個內聯表值函數通常可以解決方案 –

+0

米奇,我不得不不同意。在這種情況下,#temp表的定義是sproc和調用者之間合同的一部分。因此,如果你有適當的測試,它不會使程序難以維護。不過,我同意,它有點難看(但有時候T-SQL很醜)。 –

+0

我能想出的唯一可能是一個改進將是一個過程鍵,永久表。只要我不介意不駐留在tempdb中的輕微性能問題,並且在數據庫中有一個額外的對象,我可能就像往常一樣在測試中僞造FakeTable。 – NReilingh

回答

2

真的沒有更好的辦法。

使用#temp表作爲表值參數引用在T-SQL中本質上是醜陋的,並且也會導致測試中的醜陋。但是,您的測試看起來很周到,應該提供您正在尋找的內容。

我建議您對模式的唯一改進是在測試模式中永久創建SEtest.temptemplate表,而不是在每次測試運行時都在飛行中重新創建它。

使用SELECT ... INTO來創建測試特定的表格是我在我的測試中使用的模式。由於您無法在子程序中創建臨時表,因此這是我們唯一的乾淨選項。

無論使用哪種方式,在測試中不要使用CREATE TABLE語句來創建#temp表,因爲如果表模式發生更改,那麼這將成爲維護的噩夢。


更新:

還有就是你可能要考慮一個替代方案。由於#temp表基本上是一個表值參數,所以使用表類型不是一個壞主意。現在,這仍然是笨拙,但它所有的兩端增加可維護性:

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

這使得一個更清晰一點可讀性,特別是如果你的表類型的名稱是表現(這是在同一個模式作爲有問題的程序)。

有了這個,你可以在任何調用過程中使用相同的模式,而不僅僅是在測試中。這也使得實際的代碼更加明顯/可讀,並且如果表格定義應該改變,它會減少維護工作。

+0

更新後添加了一個讓代碼更加明顯的額外想法。 –

相關問題