2014-12-03 71 views
0

我有一個基本服務類,我的服務通常由繼承,看起來像這樣單元測試基本服務實體框架6

public abstract class BaseService<TEntity> 
    where TEntity : class, IBaseEntity 
{ 
    protected DataContext _context; 

    protected BaseService(DataContext context) 
    { 
     _context = context; 
    } 

    public virtual async Task<ICollection<TEntity>> GetAllAsync() 
    { 
     return await _context.Set<TEntity>().ToListAsync(); 
    } 

    public virtual Task<TEntity> GetAsync(long id) 
    { 
     return _context.Set<TEntity>().FindAsync(id); 
    } 

    public virtual Task<int> AddAsync(TEntity t) 
    { 
     if (_context.Entry(t).State == EntityState.Detached) 
     { 
      _context.Set<TEntity>().Add(t); 
     } 

     _context.Entry(t).State = EntityState.Added; 

     return _context.SaveChangesAsync(); 
    } 

    public virtual Task<int> AddAllAsync(ICollection<TEntity> all) 
    { 
     foreach (var item in all) 
     { 
      if (_context.Entry(item).State == EntityState.Detached) 
      { 
       _context.Set<TEntity>().Add(item); 
      } 

      _context.Entry(item).State = EntityState.Added; 
     } 

     return _context.SaveChangesAsync(); 
    } 

    public virtual Task<int> UpdateAsync(TEntity updated) 
    { 
     _context.Entry(updated).State = EntityState.Modified; 

     return _context.SaveChangesAsync(); 
    } 

    public virtual Task<int> DeleteAsync(long key) 
    { 
     return DeleteAsync(key, true); 
    } 

    public virtual async Task<int> DeleteAsync(long key, bool useFlag) 
    { 
     TEntity entity = await GetAsync(key); 
     return await DeleteAsync(entity, useFlag); 
    } 

    public virtual Task<int> DeleteAsync(TEntity t) 
    { 
     return DeleteAsync(t, true); 
    } 

    public virtual Task<int> DeleteAsync(TEntity t, bool useFlag) 
    { 
     // check if the object uses IAuditableEntity 
     IAuditableEntity auditable = t as IAuditableEntity; 

     if (useFlag && auditable != null) 
     { 
      // flag item as deleted 
      auditable.IsDeleted = true; 

      return UpdateAsync(t); 
     } 
     else 
     { 
      _context.Entry(t).State = EntityState.Deleted; 

      return _context.SaveChangesAsync(); 
     } 
    } 

} 

現在,如果我需要在從繼承的類覆蓋的方法它,我可以做到這一點。

我的問題是這些方法應該在每個從BaseService類繼承的每個類的單元測試中進行測試,還是我應該只測試單元測試我覆蓋的方法並對基本服務進行單元測試?只有這樣,baseService是抽象的,所以爲了測試它,我需要創建一個繼承它的類,以便測試它。

我是新來的單元測試,所以很抱歉,如果這是一個明顯的答案。

回答

0

是的

一般來說,你確實要測試每個後代對基地的合同。畢竟任何重寫的方法都可以包含使這個類層次結構的客戶端期望的基本行爲無效/違反的代碼。你不希望這種情況發生,所以你需要爲每個基礎服務的後代提供單元測試的早期報警系統。

這也被稱爲「合同測試」。

實現它的方法之一是創建一個(n抽象)單元測試類來驗證基類的行爲,然後爲其每個後代派生(具體)單元測試類。所有那些具體的單元測試類應該做的就是設置被測試的實例 - 這是後代類的一個實例。然後,繼承應該照顧基礎單元測試類中定義的測試方法對後代實例的運行。

如果基類是抽象的,你仍然可以在你的基類中編寫你的單元測試類。通過標記這個單元測試類抽象,你也確保測試運行器不會實例化它來運行它的測試。它只會「發現和運行」從它派生出來的具體測試類來測試基地的後代。

+0

明目張膽的自我推銷:我剛剛寫了一篇關於如何爲小型課堂層次做到這一點的博客文章[如何測試一個類層次結構而不重複自己](http://softwareonastring.com/2015/03/15/how -to-測試一個類層次結構,而無需重複的自己動手)。 – 2015-03-15 20:13:15