2014-02-25 70 views
1

我知道正確的SOLID原則與IOC相結合意味着您可以單元測試您的所有代碼,而無需通過嘲笑類依賴關係來實際訪問數據庫。在工作討論之後,我的問題是它是否值得實際測試您的數據訪問層本身。它值得自己測試數據訪問查詢嗎?

當您正確分離出您的代碼時,您的數據訪問方法通常會非常小。這裏是一個人爲的例子:

public class InvoiceQueries 
{ 
    public IEnumerable<Customer> GetAllCustomersWithOverdueInvoices(TimeSpan timeOverdue) 
    { 
     var results = 
      from invoice in Invoices 
      where invoice.DateDue - timeOverdue > DateTime.Now 
      select invoice.Customer; 

     return results; 
    } 
} 

是否值得寫的自動化測試(它不會是一個單元測試)來檢查你的查詢編寫正確?也許連接到一個真正的數據庫,甚至是內存數據庫,插入一些測試數據,然後檢查你的方法是否返回這些客戶?

一位同事說你絕對應該 - 應該測試一切。對我來說,在構建服務器上啓動和運行某種形式的T-SQL數據庫似乎是一項巨大的工作,更不用說事實上這些測試幾乎肯定會非常緩慢,並且可疑的有用性。

誰有經驗實際測試(以獨立的方式)他們的數據訪問層?

回答

0

經過一番審議,我的同事和我想出了一種方法來從持久層分離查詢。我扔在一起下面一個簡單的例子:

public class Invoice 
{ 
    public int Id {get; set;} 
    public DateTime DueOn {get; set;} 
    public DateTime MadeOn {get; set;} 
    public decimal Total {get; set;} 
    public Customer Customer {get;set;} 
} 

public class Customer 
{ 
    public int Id {get; set;} 
    public string Name {get; set;} 
} 

public class OverdueInvoice 
{ 
    public int CustomerId {get; set;} 
    public int InvoiceId {get; set;} 
    public string CustomerName {get; set;} 
    public decimal Total {get; set;} 
} 

public class InvoiceQueries 
{ 
    private readonly IReadRepository<Invoice> _invoices; 

    public InvoiceQueries(IReadRepository<Invoice> invoices) 
    { 
     _invoices = invoices; 
    } 

    public IEnumerable<OverdueInvoice> GetAllOverdueInvoices(TimeSpan timeOverdue) 
    { 
     return _invoices 
      .FindAll(invoice => invoice.DueOn - timeOverdue > DateTime.Now) 
      .Select(Map); 
    } 

    private OverdueInvoice Map(Invoice invoice) 
    { 
     return new OverdueInvoice 
     { 
      CustomerId = invoice.Customer.Id, 
      InvoiceId = invoice.Id, 
      CustomerName = invoice.Customer.Name, 
      Total = invoice.Total, 
     }; 
    } 
} 

public class InMemoryInvoicesRepository : IReadRepository<Invoice>, IWriteRepository<Invoice> 
{ 
    private List<Invoice> _backingStore; 

    public InMemoryInvoicesRepository() : this(new List<Invoice>()) 
    {} 

    public InMemoryInvoicesRepository(List<Invoice> backingStore) 
    { 
     _backingStore = backingStore; 
    } 

    public IEnumerable<Invoice> FindAll(Predicate<Invoice> predicate) 
    { 
     return _backingStore.FindAll(predicate); 
    } 

    public void Add(Invoice item) 
    { 
     _backingStore.Add(item); 
    } 
} 

public interface IReadRepository<T> 
{ 
    IEnumerable<T> FindAll(Predicate<T> predicate); 
} 

public interface IWriteRepository<T> 
{ 
    void Add(T item); 
} 

分離數據訪問到「查詢」對象和一個「資源庫」對象允許您用內存中的集合替換在測試時的資料庫。這樣,你可以用你想要的任何對象填充List,然後通過在列表中運行它來測試你的查詢層。存儲庫是一個非常笨的對象,它接受您的查詢並將其傳遞給您的ORM(實際上,這可能需要使用Expression>來替換它)。

1

是的,它應該被測試,它是值得花時間來得到它的工作(否則你會浪費時間手動測試)。是的,它比單元測試慢得多,但你可以使它足夠快(內存數據庫,所有測試的一次數據庫啓動,測試組等等)。當然你需要隔離你的業務邏輯數據庫層