C# 在Mock中检查更新的实例
我有一个方法,它调用一个服务来检索一个对象的实例,更新该实例,然后将该实例保存回该服务(代码如下) 我想知道的是,在Moq中是否有一种很好的方法来检查以下内容:-C# 在Mock中检查更新的实例,c#,unit-testing,mocking,moq,C#,Unit Testing,Mocking,Moq,我有一个方法,它调用一个服务来检索一个对象的实例,更新该实例,然后将该实例保存回该服务(代码如下) 我想知道的是,在Moq中是否有一种很好的方法来检查以下内容:- 要保存回服务的实例是原始实例的修改版本 实例已按需要更新 我知道我可以使用It.Is(x=>x.Name==newName)来检查这里的第2点。但这样做忽略了第1点 有没有一个干净的方法来实现这一点 类别代码: public class MyClass { private readonly IThingService thin
It.Is(x=>x.Name==newName)
来检查这里的第2点。但这样做忽略了第1点
有没有一个干净的方法来实现这一点
类别代码:
public class MyClass
{
private readonly IThingService thingService;
public MyClass(IThingService thingService)
{
this.thingService = thingService;
}
public void SaveMyThing(MyThing myThing)
{
var existingThing = thingService.Get(myThing.Id);
existingThing.Name = myThing.Name;
thingService.Save(existingThing);
}
}
public class MyThing
{
public int Id { get; set; }
public string Name { get; set; }
}
public interface IThingService
{
MyThing Get(int id);
void Save(MyThing myThing);
}
测试代码:
[Test]
public void Save_NewName_UpdatedThingIsSavedToService()
{
// Arrange
var myThing = new MyThing {
Id = 42,
Name = "Thing1"
};
var thingFromService = new MyThing
{
Id = 42,
Name = "Thing2"
};
var thingService = new Mock<IThingService>();
thingService
.Setup(ts => ts.Get(myThing.Id))
.Returns(thingFromService);
thingService
.Setup(ts => ts.Save(**UPDATED-THING-FROM-SERVICE**))
.Verifiable();
var myClass = new MyClass(thingService.Object);
// Act
myClass.SaveMyThing(myThing);
// Assert
thingService.Verify();
}
[测试]
public void Save\u NewName\u updatedThingsSavedToService()
{
//安排
var myThing=新的myThing{
Id=42,
Name=“Thing1”
};
var thingFromService=新神话
{
Id=42,
Name=“Thing2”
};
var thingService=new Mock();
物流服务
.Setup(ts=>ts.Get(myThing.Id))
.返回(服务中的内容);
物流服务
.Setup(ts=>ts.Save(**UPDATED-THING-FROM-SERVICE**))
.可验证();
var myClass=newmyclass(thingService.Object);
//表演
myClass.SaveMyThing(myThing);
//断言
thingService.Verify();
}
您就快到了:
[Test]
public void Save_NewName_UpdatedThingIsSavedToService()
{
// Arrange
var myThing = new MyThing {
Id = 42,
Name = "Thing1"
};
var thingFromService = new MyThing
{
Id = 42,
Name = "Thing2"
};
var thingService = new Mock<IThingService>();
thingService
.Setup(ts => ts.Get(myThing.Id))
.Returns(thingFromService)
.Verifiable();
thingService
.Setup(ts => ts.Save(It.Is<MyThing>(x => x.Name == myThing.Name)))
.Verifiable();
var myClass = new MyClass(thingService.Object);
// Act
myClass.SaveMyThing(myThing);
// Assert
thingService.Verify();
}
[测试]
public void Save\u NewName\u updatedThingsSavedToService()
{
//安排
var myThing=新的myThing{
Id=42,
Name=“Thing1”
};
var thingFromService=新神话
{
Id=42,
Name=“Thing2”
};
var thingService=new Mock();
物流服务
.Setup(ts=>ts.Get(myThing.Id))
.Returns(thingFromService)
.可验证();
物流服务
.Setup(ts=>ts.Save(It.Is(x=>x.Name==myThing.Name)))
.可验证();
var myClass=newmyclass(thingService.Object);
//表演
myClass.SaveMyThing(myThing);
//断言
thingService.Verify();
}
主要区别在于,我还在第一次设置中添加了对Verifiable()
的调用,然后我添加了It.is
检查您在回答中已经提到的内容。由于谓词的原因,只有当谓词的计算结果为true时,才会匹配Save方法,在这种情况下,Verify
调用成功
然而,这个测试实际上测试了两件事(Get和Save)。为了避免这种情况,最好将其分为两个测试。如果我理解正确,您需要验证传递给
ts.Save
的参数是否是从服务返回的实例
如果这是真的,除了验证Name
值是否满足您的期望之外,还要检查引用相等性:
thingService
.Setup(ts => ts.Save(It.Is<MyThing>(thing => thing == thingFromService
&& thing.Name = myThing.Name))
.Verifiable();
thingService
.Setup(ts=>ts.Save(It.Is(thing=>thing==thingFromService
&&thing.Name=myThing.Name)
.可验证();
我同意Mark的回答,但你的第一句话让我有点困惑。你是想知道对象是相同的对象引用还是对象类型?It只是确保参数是虚构的类型,而不是对上一个对象的实际引用
如果要截获传递给模拟服务的值,可以使用如下回调,然后对结果对象执行任何您想要的断言:
MyThing result = null;
thingService
.Setup(ts => ts.Save(It.Is<MyThing>(x => x.Name == myThing.Name)))
.Callback((MyThing saved) => result = saved)
.Verifiable();
MyThing result=null;
物流服务
.Setup(ts=>ts.Save(It.Is(x=>x.Name==myThing.Name)))
.Callback((虚构保存)=>result=保存)
.可验证();
Yep,我理解这一点。对thingService的“Get”调用实际上是一个存根(而不是模拟),因此它不需要.Verify()。这段代码的问题是它没有区分传递更新版本的“thingFromService”实例传递给Save方法,并将传递给SaveMyThing方法的神话实例传递给SaveMyThing方法(我的问题中的第1点)。:-(我想检查它是否是与更新的propertyFantastic相同的对象引用!我希望“thing==thingFromService”返回false作为“thing.Name!=thingFromService.Name”.事实并非如此,因为thingFromService是在测试方法中更新的对象,因此也是一样的。这是漫长的一天;-)谢谢Jeff!