2012-04-24 147 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

工作单元模式的巨大优势在于它从其消费者中提取数据源,让您决定如何在测试中实现它。

你可以选择走嘲讽路线,正如你所说的那样,每次测试都有一点配置开销;或者您可以创建一个具体的类来实现您的工作单元,并将其用作有状态测试的双重功能。

根据我的经验,测试与测试双重方法有所不同 - 测试并不在乎使用工作单元的次数或顺序,而是关注最终结果。