2012-07-05 58 views
2

我有一個使用LINQ to SQL實現的存儲庫。我需要做單元測試,儘管我沒有數據庫。我怎樣才能寫FreezeAllAccountsForUser方法的UT?你可以使用手動模擬演示一個例子嗎?沒有數據庫的單元測試:Linq to SQL

注:有一個在域中使用的繼承映射對象

注:單元測試是使用從@StuperUser Visual Studio團隊測試

評論來完成。單元測試涉及將代碼與其交互的其他對象完全隔離。這意味着,如果代碼失敗,您可以確定失敗與被測代碼有關。要做到這一點,你必須僞造這些對象。

CODE

 public void FreezeAllAccountsForUser(int userId) 
    { 
     List<DTOLayer.BankAccountDTOForStatus> bankAccountDTOList = new List<DTOLayer.BankAccountDTOForStatus>(); 

     IEnumerable<DBML_Project.BankAccount> accounts = AccountRepository.GetAllAccountsForUser(userId); 
     foreach (DBML_Project.BankAccount acc in accounts) 
     { 
      string typeResult = Convert.ToString(acc.GetType()); 
      string baseValue = Convert.ToString(typeof(DBML_Project.BankAccount)); 

      if (String.Equals(typeResult, baseValue)) 
      { 
       throw new Exception("Not correct derived type"); 
      } 

      acc.Freeze(); 

      DTOLayer.BankAccountDTOForStatus presentAccount = new DTOLayer.BankAccountDTOForStatus(); 
      presentAccount.BankAccountID = acc.BankAccountID; 
      presentAccount.Status = acc.Status; 
      bankAccountDTOList.Add(presentAccount); 

     } 



     IEnumerable<System.Xml.Linq.XElement> el = bankAccountDTOList.Select(x => 
         new System.Xml.Linq.XElement("BankAccountDTOForStatus", 
          new System.Xml.Linq.XElement("BankAccountID", x.BankAccountID), 
          new System.Xml.Linq.XElement("Status", x.Status) 
         )); 

     System.Xml.Linq.XElement root = new System.Xml.Linq.XElement("root", el); 


     //AccountRepository.UpdateBankAccountUsingParseXML_SP(root); 
     AccountRepository.Update(); 

    } 

庫層

namespace RepositoryLayer 
{ 
public interface ILijosBankRepository 
{ 
    System.Data.Linq.DataContext Context { get; set; } 
    List<DBML_Project.BankAccount> GetAllAccountsForUser(int userID); 
    void Update(); 

} 

public class LijosSimpleBankRepository : ILijosBankRepository 
{ 
    public System.Data.Linq.DataContext Context 
    { 
     get; 
     set; 
    } 


    public List<DBML_Project.BankAccount> GetAllAccountsForUser(int userID) 
    { 
     IQueryable<DBML_Project.BankAccount> queryResultEntities = Context.GetTable<DBML_Project.BankAccount>().Where(p => p.AccountOwnerID == userID); 
     return queryResultEntities.ToList(); 
    } 


    public virtual void Update() 
    { 
     //Context.SubmitChanges(); 
    } 

} 

} 

域類

namespace DBML_Project 
{ 

public partial class BankAccount 
{ 
    //Define the domain behaviors 
    public virtual void Freeze() 
    { 
     //Do nothing 
    } 
} 

public class FixedBankAccount : BankAccount 
{ 

    public override void Freeze() 
    { 
     this.Status = "FrozenFA"; 
    } 
} 

public class SavingsBankAccount : BankAccount 
{ 

    public override void Freeze() 
    { 
     this.Status = "FrozenSB"; 
    } 
} 
} 

自動生成的類由LINQ到SQL

[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.BankAccount")] 
[InheritanceMapping(Code = "Fixed", Type = typeof(FixedBankAccount), IsDefault = true)] 
[InheritanceMapping(Code = "Savings", Type = typeof(SavingsBankAccount))] 
public partial class BankAccount : INotifyPropertyChanging, INotifyPropertyChanged 

回答

2

存儲庫的責任是堅持域對象並根據請求獲取它們。即它的工作是將對象和反序列化/序列化爲某種形式的持久存儲。

因此,存儲庫的測試必須在這種情況下針對實際存儲進行測試。即這些是集成測試 - 測試您的課程是否與外部數據庫集成。

一旦你有了這個釘子,客戶端/應用程序的其餘部分就不必對真實的數據庫進行操作。他們可以模擬知識庫並進行快速的單元測試。您可以假設GetAccount在集成測試通過後起作用。

更多細節: 通過在Repository對象傳遞的構造函數或方法ARG,你打開門傳遞一個假的或者是模擬。因此,現在服務測試可以在沒有真實存儲庫的情況下運行>>沒有DB訪問>>快速測試。

public void FreezeAllAccountsForUser(int userId, ILijosBankRepository accountRepository) 
{ 
    // your code as before 
} 

test() 
{ var mockRepository = new Mock<ILijosBankRepository>(); 
    var service = // create object containing FreezeAllAccounts... 

    service.FreezeAllAccounts(SOME_USER_ID, mockRepository); 

    mock.Verify(r => r.GetAllAccountsForUser(SOME_USER_ID); 
    mock.Verify(r => r.Update()); 
} 
+0

謝謝。 「他們可以模擬知識庫並進行快速的單元測試。」你能解釋一下單元測試的樣子嗎? – Lijo 2012-07-06 08:56:07

+0

你能解釋一下如何測試不是存儲庫方法的FreezeAllAccountsForUser方法嗎? – Lijo 2012-07-06 09:11:35

+0

謝謝。這是用於模擬的工具嗎? – Lijo 2012-07-06 15:13:09

5

簡而言之,你做不到。存儲庫實現的唯一目的是與數據庫交談。所以數據庫技術很重要,您應該執行集成測試。

單元測試此代碼是不可能的,因爲LINQ to Objects是LINQ to SQL的超集。你可能會有一個綠色的單元測試,並且在使用真實數據庫時仍然會得到運行時異常,因爲你的存儲庫中使用了無法轉換爲SQL的LINQ功能。

+0

但以下帖子說這種方法。你怎麼看? http://stackoverflow.com/questions/7076726/how-to-test-my-linq-repository-calls另見http://stackoverflow.com/questions/4649786/unit-testing-practice-with-linq-to -sql – Lijo 2012-07-06 05:53:59

+0

想象一個簡單的例子:您在實體中創建了一個未映射到表格單元但以某種方式計算的自定義屬性。在where子句中使用該屬性的存儲庫methot將通過單元測試並在集成測試中失敗。 – 2012-07-06 08:28:46

+2

編寫錯誤肯定的單元測試有什麼意義? – 2012-07-06 08:56:34

0

您可以通過在datacontext中使用IDbSet接口併爲datacontext類提取接口。編程接口是創建單元可測試代碼的關鍵。

您希望爲這些linq查詢創建單元測試的原因是對邏輯查詢進行單元測試。集成測試受到各種誤報的影響。數據庫沒有處於正確的狀態,其他查詢同時運行,其他集成測試等。爲了進行可靠的集成測試,要很好地隔離數據庫非常困難。這就是集成測試常常被忽略的原因。如果我必須選擇一個,我想單元測試...