C# 如何在moq中调试验证?

C# 如何在moq中调试验证?,c#,.net,unit-testing,moq,autofixture,C#,.net,Unit Testing,Moq,Autofixture,我正在使用IDatabase类为数据库调用方法提供的NPoco。我想验证进入NPoco Insert方法的对象是否具有正确的数据(以域对象的形式) 你需要使你的模拟呼叫可验证 unitOfWork .Setup(x => x.Db.Insert(It.IsAny<MyDomainObject>())) .Verifiable(); 工作单元 .Setup(x=>x.Db.Insert(It.IsAny()) .可验证(); 中的代码使用IUnitOfWorkP

我正在使用IDatabase类为数据库调用方法提供的NPoco。我想验证进入NPoco Insert方法的对象是否具有正确的数据(以域对象的形式)


你需要使你的模拟呼叫可验证

unitOfWork
    .Setup(x => x.Db.Insert(It.IsAny<MyDomainObject>()))
    .Verifiable();
工作单元
.Setup(x=>x.Db.Insert(It.IsAny())
.可验证();
中的代码使用IUnitOfWorkProvider生成IUnitOfWork:

using (var unitOfWork = unitOfWorkProvider.GetUnitOfWork())
{
    MyDomainObject myDomain = anotherService.getMyDomain(DateTime.Now, 100);
    unitOfWork.Db.Insert(myDomain); 
}
您当前尝试模拟的IUnitOfWork实例是一些其他实例。它们不是由此IUnitOfWorkProvider生成的

假设IUnitOfWorkProvider被注入到SUT中,您应该能够冻结它并从那里开始。这样的事情应该行得通:

var fixture = new Fixture().Customize(new AutoMoqCustomization());
var uowProviderStub = fixture.Freeze<Mock<IUnitOfWorkProvider>>();
var uowMock = fixture.CreateAnonymous<Mock<IUnitOfWork>>();
var sut = fixture.CreateAnonymous<MyService>();

uowProviderStub.Setup(p => p.GetUnitOfWork()).Returns(uowMock.Object);
uowMock
    .Setup(x => x.Db.Insert(It.IsAny<MyDomainObject>()))
    .Verifiable();

// etc.
var fixture=newfixture().Customize(新的AutoMoqCustomization());
var uowProviderStub=fixture.Freeze();
var uowMock=fixture.CreateAnonymous();
var sut=fixture.CreateAnonymous();
设置(p=>p.GetUnitOfWork()).Returns(uowMock.Object);
uowMock
.Setup(x=>x.Db.Insert(It.IsAny())
.可验证();
//等等。

这真的有点麻烦,这是一个测试,它试图告诉你设计不是最好的…

为什么?我试过了,但还是失败了。我仍然得到Moq.MockException:调用没有在mock:x=>x.Db上执行。Insert(It.IsAny())MockException还包含执行的调用(如果有),您可以将完整的异常文本粘贴到这里吗?Moq.MockException:调用没有在Moq.mock.ThrowVerifyException上的mock:x=>x.Db.Insert(It.IsAny())上执行Moq.Mock.VerifyCalls(侦听器targetInterceptor,MethodCall,表达式表达式,时间)Moq.Mock.Verify[T,TResult](Mock,Expression
1 Expression,Times,Times,String failMessage)Moq.Mock
1.Verify[TResult](Expression`1 Expression,Times)在第393行的Tests.Services.ServiceTests.Test()中,我可以看到,您的设置不是模拟的,即您可以执行
x.Db
,但是当您进入另一个级别时,您就超出了设置表达式可以执行的范围,
Verify()
工作[正如您所调用的
x.Db
]。但可能您剥离了太多内容。正如Ruben所怀疑的那样,
IDatabase Db
会自动模拟,并且您对错误的对象设置了期望值。通常,在执行
x=>x.Db…
位(
Db
为null)时,您会得到null引用异常,但由于您使用AutoFixture,它会悄悄地传递。您的上一个示例之所以有效,是因为对
工作单元
没有任何期望。我建议您
冻结
数据库
,并对其设置期望。@rubenbarterink Moq创建了所谓的自动模拟层次结构(也称为递归模拟)-因此,只要是虚拟的或抽象的,你就可以按你的意愿点下任意多个级别-这样Moq就可以代理它们。我厌倦了冻结IDatabase,但不确定如何处理冻结的mock。当我只是冻结它,不做任何事时,测试仍然失败。当我调试IDatabase时,似乎总是有相同的数字(所以我认为是同一个物体)@jimmy_keen-我用我最新的尝试更新了我的帖子,但它们仍然不起作用。那么,你如何绕过德米特定律?我的意思是,我的工作单元是如何设置的。要摆脱IUnitOfWorkProvider,你可以直接将IUnitOfWork注入服务,并在你的Compositi中管理服务的生命周期和UoW在根目录上。@chobo2另一种方法是通过使用AutoFixture.xUnit和/或进行自定义,以执行
uowProviderStub.Setup(p=>p.GetUnitOfWork()).Returns(uowMock.Object)来掩盖问题
有点幕后。但请不要这样做-使用Mark的适当解决方案我仍然不明白为什么它不使用同一个对象。我需要UnitOfWorkProvider的原因是要创建更多的工作单元。我可能会在我的服务中调用几个方法,每个方法都需要自己的工作单元。我需要什么样的应用程序ou楼宇?网络应用程序?桌面应用程序?
using (var unitOfWork = unitOfWorkProvider.GetUnitOfWork())
{
    MyDomainObject myDomain = anotherService.getMyDomain(DateTime.Now, 100);
    unitOfWork.Db.Insert(myDomain); 
}
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var uowProviderStub = fixture.Freeze<Mock<IUnitOfWorkProvider>>();
var uowMock = fixture.CreateAnonymous<Mock<IUnitOfWork>>();
var sut = fixture.CreateAnonymous<MyService>();

uowProviderStub.Setup(p => p.GetUnitOfWork()).Returns(uowMock.Object);
uowMock
    .Setup(x => x.Db.Insert(It.IsAny<MyDomainObject>()))
    .Verifiable();

// etc.