我正在使用工作单元模式和我的数据层。
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;
}
}
(测试)使用Moq
[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(和result2)为null。我意识到这是因为我没有直接实例化属性。但我想知道是否有办法不必模拟模拟内部的属性。如果没有Moq那么可能还有其他一些模拟框架?
答案 0 :(得分: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);
请注意,您现在必须.Setup
GetAll
和class1Mock
class2Mock
class1Mock
.Setup(c => c.GetAll())
.Returns(new [] { new Class1 {...} }.AsQueryable());
{/ 1}}
{{1}}
如果你希望对你的嘲讽有这种控制,那么恐怕没有捷径可走。
注意:即使它对您的情况没有帮助(因为您希望直接控制模拟),AutoFixture with Moq绝对值得在类似情况下查看。
答案 1 :(得分:0)
工作单元模式的巨大优势在于它从消费者那里抽象出数据源,让您决定如何在测试中实现它。
你可以选择去模拟路由,你已经避开了每个测试的一些配置开销;或者您可以创建一个实现您的工作单元的具体类,并将其用作有状态测试double。
根据我的经验,测试感觉与测试双重方法不同 - 测试并不关心使用工作单元的次数或顺序,而是关注最终结果。