簡體   English   中英

如何用單元測試測試以下場景?

[英]How is the following scenario tested with a unit test?

我將對以下內容進行單元測試還是進行其他類型的測試:

我想更新數據庫中的值,更新值之后,我要確保數據庫已使用正確的值更新,但這意味着我必須查詢數據庫並確定是否存在正確的值,並且我認為單元測試,接觸數據庫是不行的。

我想對以下方法進行單元測試(db和Update組成):

public void UpdateValue(int value)
{
   db.Update(value);
}

您可以簡單地測試您的方法是否成功調用了數據庫。 嘲笑往往專注於此,您希望發生的呼叫確實發生。

它將涉及用測試版本替換db ,以便您對UpdateValue的測試將斷言它希望使用相同的值來調用db.Update(value)

應該完成存儲過程或SQL的測試(最終,它仍然有可能發生與C#代碼相同的錯誤可能性),但是可能獨立於代碼單元測試而完成。 我們有一個單獨的測試項目,用於測試存儲過程邏輯。 由於這涉及物理數據庫,因此將其保持獨立且最小化-但是我們仍然認為它是必不可少的。 我們已經進入測試幾乎所有數據庫腳本的階段,但是從一開始,您通常可以不用測試基本的CRUD代碼。 任何具有條件語句的SQL都將受到測試。

如果要進行端到端測試以查看是否可以使用代碼將代碼保存到數據庫並再次獲取值, 那么按照定義,這不是單元測試。 @lazyberezovsky所述 ,這是一個集成測試。 單元測試旨在刪除代碼單元周圍的所有依賴性,以便僅測試該單元。

就是說,(我認為)必須進行集成測試。 我們將它們與用例相對應,以便我們測試用戶作為用例操作簽署的內容。 這一口氣砸了很多代碼,但是有一個明顯的缺點 ,就是要與共享狀態/副作用代碼作斗爭。 您會發現,對於集成測試,測試的大部分是准備工作,而不是代碼聲明。 您還發現它們無法識別出失敗的特定代碼,因此診斷集成測試失敗更加困難。

我們在集成測試中處於中間立場。 我們的數據庫是通過DAL接口提供的,我們只需對該接口進行存根(不同於模擬),以便提供與物理數據庫相對的內存中測試數據。 這樣做的缺點是我們錯過了對數據庫本身的集成測試。

對象的責任是將值傳遞給它的依賴項(數據庫)。 因此,注入一些抽象,它代表對象的數據庫:

public Foo(IDatabase db)
{
   _db = db;
}

並驗證此依賴項與要測試的對象之間的交互:

Mock<IDatabase> db = new Mock<IDatabase>();
db.Setup(x => x.Update(5));
Foo foo = new Foo(db.Object);
foo.Update(5);
db.VerifyAll();

沒錯, 在單元測試中接觸數據庫是不行的。 單元測試應僅驗證一個單元的行為(隔離)。 如果要檢查幾個協同工作的單元(您的foo和db),則需要進行集成測試 ,以驗證數據庫中實際更改的數據。

更新:此示例中使用了Moq框架。

實際上,根據純粹主義者的定義,接觸數據庫的測試不是“單元測試”,而是“集成測試”。

典型的答案是用模擬代替對db.Update()的調用,但是在某些情況下,您可能會覺得自己測試的代碼不夠多。

根據您使用的數據庫,可能還有其他選擇。 如果使用SQL Server,則可以對本地文件SQL Express db執行單元測試。 每次執行單元測試時,都可以使用原始的干凈副本覆蓋該文件,因此您的測試也變得非常可重復。 您需要做的就是用單元測試代碼部署SQL Express數據庫,並在單元測試app.config中將連接字符串設置為該本地db。

重要的是要記住,單元測試並不是所有自動化軟件測試的完美解決方案。

您描述的情況通常以兩種方式進行測試:

  • 首先,您將單元測試作為常規開發的一部分,並且該測試將僅確保使用適當的值調用依賴關系(如Adam Houldsworth和lazyberezovsky答案中所述)。 這只是告訴您(和其他開發人員) 此代碼可以做到這一點,這就是證明
  • 接下來,進行集成測試。 此測試需要真實的組件和適當的設置(如有效配置中的,沒有/最少數量的模擬)。 該測試表明,您的組件(或整個應用程序)在實際情況下可以正常工作並進行交互。

每種類型的測試都有其位置,您通常希望同時擁有它們。

我將使用一個更具體的示例,因為它會更容易討論。 假設UpdateValue實際上位於零售系統中的某處,用新的美分值更新了舊價格。

也許您的班級負責提供當前價格或歷史價格-我們稱其為PriceProvider 也許它知道如何為收據提供退款價格。 也許它知道如何給白色冰箱冰櫃定價。 它還知道如何使用便士提供的新價格更新價格。 如果這是它的工作,那么它應該不知道價格存儲在哪里,因為它已經承擔了一項責任(單一責任原則)。 它應該將檢索價格的職責委托給其他人,它的工作是將業務請求轉換為對知道價格存儲位置的對象的參數化調用。

或者,也許您的班級負責從數據庫中檢索價格並將價格更新到數據庫( DatabasePriceRepository 它知道如何查找日期和項目的價格,或獲取日期和類別的價格的列表,但並不關心為什么要查找它。 如果這是您的課程,則它與數據庫緊密耦合-這是它的唯一責任-因此,嘲笑這一點毫無意義,否則該課程將毫無價值。 相反,您可以通過進行集成測試或編寫全棧方案,甚至通過手動測試來對其進行測試。

我在使用Hibernate的項目中工作,並通過實例化不同的對象來測試配置文件。 我們將Hibernate連接到內存數據庫來完成此操作。 那非常快,給了我們非常迅速的反饋! 我還曾在從UI到數據庫的端到端場景中工作過,在其他地方我們通過用HTTP請求命中並檢查響應來測試某些服務,而在其他地方則手動進行了測試。

無論您是否對該類進行單元測試,在某些時候都必須接觸生產環境中的數據庫,而且我敢肯定,在上線之前必須進行測試。 如果您對該類進行單元測試,則需要在其他任何地方(自動或其他方式)執行集成測試。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM