2012-04-24 243 views
1

我正在使用工作單元模式和我的數據層。模擬方法調用模擬對象中的屬性

public interface IUnitOfWork{ 
    IRepository<Class1> Class1s {get;} 
    IRepository<Class2> Class2s {get;} 
    ... 
} 

public interface IRepository<T> where T:class{ 
    IQueryable<T> GetAll(); 
} 

這與我的代碼庫正常工作;但是,我在我的服務層中測試此 時遇到問題。

public class SomeService{ 
    private readonly IUnitOfWork uow; 
    public SomeService(IUnitOfWork u){ 
     uow = u; 
    } 

    public IEnumerable<ViewModel1> GetViewModel(){ 
     var result1 = uow.Class1s.GetAll(); 
     var result2 = uow.Class2s.GetAll(); 
     var query = from r1 in result1 
        from r2 in result2 
         where r1.key == r2.key 
         select new ViewModel1{...}; 
     return result; 
    } 
} 
使用起訂量

[Test] 
public void TestMethod(){ 
    var uow = new Mock<IUnitOfWork>(); 
    uow.Setup(u => u.Class1s.GetAll()).Returns(new []{ new Class1{...}}.AsQueryable()); 
    uow.Setup(u => u.Class2s.GetAll()).Returns(new []{ new Class2{...}}.AsQueryable()); 
    var service = new SomeService(uow.Object); 
    var result = service.GetViewModel(); 
    Assert.AreEqual(1,result.Count()); 
} 

測試

(測試)拋出一個異常說RESULT1(和結果2)爲空。我意識到這是因爲我沒有直接實例化屬性。但我想知道是否有辦法不必模擬模擬內的屬性。如果不是Moq,那麼也許還有其他一些嘲諷的框架?

回答

3

不,Moq不會幫你在這裏。你必須手動設置它們(雖然你可以藏漢嘲笑他們):

var class1Mock = new Mock<IRepository<Class1>>(); 
var class2Mock = new Mock<IRepository<Class2>>(); 
var uow = new Mock<IUnitOfWork>(); 
uow.Setup(u => u.Class1).Returns(class1Mock.Object); 
uow.Setup(u => u.Class2).Returns(class2Mock.Object); 

注意,你現在就必須爲GetAll.Setupclass1Mockclass2Mock

class1Mock 
    .Setup(c => c.GetAll()) 
    .Returns(new [] { new Class1 {...} }.AsQueryable()); 

如果您想要對你的嘲笑有這種控制,恐怕沒有捷徑。

注意:即使它不會幫助你的情況(因爲你想直接控制嘲笑),AutoFixture with Moq絕對值得在類似的情況下檢查。

0

工作單元模式的巨大優勢在於它從其消費者中提取數據源,讓您決定如何在測試中實現它。

你可以選擇走嘲諷路線,正如你所說的那樣,每次測試都有一點配置開銷;或者您可以創建一個具體的類來實現您的工作單元,並將其用作有狀態測試的雙重功能。

根據我的經驗,測試與測試雙重方法有所不同 - 測試並不在乎使用工作單元的次數或順序,而是關注最終結果。