2017-09-04 127 views
2

我正在使用.NET Core 2.0和.NET Core MongoDB驅動程序。使用IMongoQueryable進行單元測試

我已經創建了一個信息庫,像這樣:

public interface IRepository<T> 
{ 
    IMongoQueryable<T> Get() 
} 

我這樣做給靈活性,誰使用這是能夠做到的LINQ就像他們會做使用EF。問題是當涉及到單元測試時,我正嘗試創建一個內存數據庫,以便在操作之前和之後檢查狀態。

一些東西,我想:

public class InMemoryRepository : IRepository<ConcreteType> 
{ 
    private HashSet<ConcreteType> _data = new HashSet<ConcreteType>(); 

    public IMongoQueryable<ConcreteType> Get() 
    { 
     return (IMongoQueryable<ConcreteType>)_data.AsQueryable(); 
    } 
} 

的情況下不作爲接口連續工作IMongoQueryable是:

public interface IMongoQueryable<T> : IMongoQueryable, IQueryable, IEnumerable, IQueryable<T>, IEnumerable<T>, IAsyncCursorSource<T> 

別的去了:

public class InMemoryRepository : IRepository<ConcreteType> 
{ 
    private HashSet<ConcreteType> _data = new HashSet<ConcreteType>(); 

    public InMemoryRepository() 
    { 
     _mongoQueryableMock = new Mock<IMongoQueryable<ConcreteType>>(); 
     _mongoQueryableMock.Setup(m => m.AsQueryable()).Returns(_data.AsQueryable); 
    } 

    public IMongoQueryable<ConcreteType> Get() 
    { 
     return _mongoQueryableMock.Object; 
    } 
} 

這不工作爲IMongoQueryable.AsQueryable()是一種擴展方法,我不能嘲笑/設置。

+1

嘲諷的IQueryable接口是很困難的和危險的,因爲你不能正確地模仿執行的行爲。因此,您的可能通過,但它不會對實際的MongoDb實例工作。資源庫的作用是將數據訪問技術從應用程序的業務邏輯中抽象出來。如果您的資源庫向您的業務層公開了MongoDb特定的接口,那麼您有一個漏洞抽象。您冒着將您的業務邏輯與特定的數據訪問技術聯繫起來的風險。 –

回答

1

將模擬配置爲能夠處理IQueryable調用。

public class InMemoryRepository : IRepository<ConcreteType> { 
    private HashSet<ConcreteType> _data = new HashSet<ConcreteType>(); 
    private Mock<IMongoQueryable<ConcreteType>> _mongoQueryableMock; 

    public ReviseMeasureRepository() {  
     var queryableList = _data.AsQueryable(); 

     _mongoQueryableMock = new Mock<IMongoQueryable<ConcreteType>>(); 
     _mongoQueryableMock.As<IQueryable<ConcreteType>>().Setup(x => x.Provider).Returns(queryableList.Provider); 
     _mongoQueryableMock.As<IQueryable<ConcreteType>>().Setup(x => x.Expression).Returns(queryableList.Expression); 
     _mongoQueryableMock.As<IQueryable<ConcreteType>>().Setup(x => x.ElementType).Returns(queryableList.ElementType); 
     _mongoQueryableMock.As<IQueryable<ConcreteType>>().Setup(x => x.GetEnumerator()).Returns(() => queryableList.GetEnumerator());  
    } 

    public IMongoQueryable<ConcreteType> Get() { 
     return _mongoQueryableMock.Object; 
    } 

    //... 
} 

有了這樣的,我認爲庫的設計泄漏,並直接將你的代碼到外部依賴的方式。考慮審查存儲庫抽象的設計。

+0

我不確定這是否超出了這個問題的範圍,但你有什麼想法嗎?如果我想使用'.Take()'和'.Offset()',我將不得不爲這些編寫特定的方法。我試圖做到這一點,以便存儲庫不與其他CRUD方法耦合併成功,但我找不到用於返回集合的快樂媒體。我顯然不希望返回數據庫中的所有內容,並讓他們在內存中過濾他們想要的內容。 –

+1

@KevinLee,這是一個全新的問題。這也是抽象的抽象問題。摘要所需的行爲。因此,讓您的API更加針對您想要公開的內容。暴露IQueryable是漏洞。 '.Take()'和'.Offset()'是實現問題,應該通過實現期望的行爲來封裝。 – Nkosi