2011-11-18 88 views
1

我有這樣的方法如下:如何測試具有數據庫查詢以更新數據的方法?

public void ImportDataCommand() 
{ 
    // some data validation logic here 

    if (some_criteria_is_true) 
    { 
     // Call to a method which uses sql queries to update some records 
     UpdateRecords(); 
    } 
    else 
    { 
     // Call to a method which uses sql queries to delete some records 
     DeleteRecords(); 
    } 
} 
  • 我怎麼能單元測試方法UpdateRecords()DeleteRecords()? (如果可能的話)
  • 我目前的模式, 的氣味?
  • 有沒有更好的方法來處理,當你有一些數據 更新邏輯,這取決於一些數據驗證邏輯和一些 條件邏輯?

在這方面的任何幫助,非常感謝。請讓我知道,如果你需要更多的信息,或者如果有什麼不明確的。

更新:

我沒有興趣在這裏嘲諷的數據源。我想確保我的sql查詢是否正確,並且正在做正確的更新。對不起,如果你想,我想測試我的驗證邏輯,而不是我的數據更新邏輯(sql)。

我確實有嘲笑框架的經驗,我成功地使用它們爲我的正常應用程序邏輯編寫單元測試。

+0

你的方法不會返回任何東西 - 通常,單元測試會給你一堆參數,並測試返回的值是否符合期望值。 –

+0

@尼維爾:對。比方說,我想測試一個應用程序命令,它將數據存儲/更新到數據庫中。有沒有辦法做到這一點? - 我已經使用NUnit爲我的正常應用程序邏輯成功編寫了單元測試。 –

+0

執行此操作的常用方法是使用模擬框架,因此您可以將測試與其下的特定數據庫分離。 –

回答

3

您的問題始於短語'以及'

不要在同一個類中進行驗證和數據訪問 - 將數據訪問委派給另一個類並注入它 - 這樣,您可以在測試驗證時嘲笑數據源。

class Bar { 
private DataAccessService service 

public void Foo() 
{ 
    // some data validation logic here 

    if (some_criteria_is_true) 
    { 
     // Call to a method which uses sql queries to update some records 
     service.updateBarRecords(); 
    } 
    else 
    { 
     // Call to a method which uses sql queries to delete some records 
     service.deleteBarRecords(); 
    } 
} 

} 

然後,您可以使用模擬框架來測試是否調用了正確的服務方法。

+0

對不起,我感到困惑。我想測試我的數據更新邏輯而不是驗證邏輯。請參閱我對該問題所做的更新。 –

+0

如果Foo()不是你想測試的方法,那麼你可能應該問一個關於如何測試UpdateBarRecords()的問題...... – blank

+0

你是對的。我現在更新了我的問題以反映這一點。謝謝。 –

0

這取決於您的應用程序的整個架構和公司的IT/DB基礎架構,以及數據庫管理員可以在中型企業或大公司中強制執行的數據策略。

過去人們曾經爲SQLite實例進行單元測試,或者您可以使用相同的技術(例如SQL Server),但有單元測試連接到開發或QA數據庫服務器,當然不是生產。

我過去做過的一件事是在命令執行周圍進行事務處理,最後在單元測試中回滾事務,因此DEV/QA數據庫中沒有任何內容持久化,但命令執行的測試無論如何都是執行的。

+0

您通常會嘲笑數據庫本身來進行單元測試,而不是在生產數據庫上進行單元測試,因爲您必須注意回滾和填充內容。我從以前的項目中看到的是,他們使用NUNIT構建的預處理器指令,然後將SQL執行重定向到一個不同的(注入)數據庫,在這裏你不需要關心回滾或以前的事情。在每件事情完成後刪除就是kool。 :) – Zenwalker

0

當你做單元測試時,你特別只關注那個單元,例如這裏的一個方法。所以當你編寫一個測試用例時,你可以模擬通常通過依賴注入調用的其他方法(如果它是API調用或某種東西)。其他方面,你只是猜測和寫出測試用例。因此,在您的代碼案例中,假設您分別爲Foo(),UpdateBarRecords()和DeleteBarRecords()編寫測試用例。

忽略所有的方法調用(對它進行單元測試)並專注於您在該方法中編寫的核心邏輯代碼,這些代碼將專注於單元測試。

0

恕我直言,你應該解決您的代碼這個問題:

  1. 富不是單位testeable,因爲它不返回任何東西
  2. 你連接到你的應用程序邏輯的數據訪問,這使得不同的層太捆綁在一起,實際上單元測試它們
  3. 也許一種方法,您根據某種條件調用更新和刪除是一種氣味......應該不是更好有兩種不同的行爲?

既然Foo的命名不是自我解釋,那麼沒有其他的東西了,但是如果你能詳細描述方法的上下文,我們可以添加更多的評論。

+2

不返回東西不會使它無法測試 – blank

+0

@Bedwyr,除非我遺漏了我確認的東西:您可以測試一次執行該方法的可見效果,但是您不能單元測試*方法*本身。 – mamoo

+0

您可以測試該方法是否具有正確的行爲 - 它必須執行某些操作 - 這就是您可以測試的方法,可以通過聲明狀態已在類中的其他位置進行更改,或者方法調用依賴性上的預期方法。 – blank