[英]Moq - mocking factory not generating new object with each iteration
I'm trying to moq and test the following method:我正在尝试最小起订量并测试以下方法:
public List<SkuCountByRetailerVm> GetSkuCountsByRetailer()
{
var viewModels = _factory.GetEmptyListOfSkuCountByRetailerVms();
foreach (var retailer in _helper.GetAllRetailersInReading())
{
var vm = _factory.GetSkuCountsByRetailerVm();
vm.Retailer = retailer;
vm.SkuCount = _helper.GetSkuCountByRetailerInReading(retailer);
viewModels.Add(vm);
}
return viewModels;
}
The SkuCountByRetailerVm class is very basic data transfer object, it has got Retailer and SkuCount properties. SkuCountByRetailerVm 类是非常基本的数据传输对象,它具有 Retailer 和 SkuCount 属性。
The class under test depends on IFactory and IHelper, both of which I'm mocking in the test class.被测类依赖于 IFactory 和 IHelper,我在测试类中模拟了这两个类。
It looks like the code for the class under test is fine.看起来被测类的代码很好。 The problem when mocking is that I get 3 same viewmodels added to the list (all like the one which I expect to be added as last one), instead of 3 different ones.嘲笑时的问题是我将 3 个相同的视图模型添加到列表中(所有这些都类似于我希望添加为最后一个的视图模型),而不是 3 个不同的视图模型。 I think the problem with my test is that the way I setup the moq of the factory mockFactory.Setup(m => m.GetSkuCountsByRetailerVm()).Returns(new SkuCountByRetailerVm());
我认为我的测试的问题在于我设置工厂的起mockFactory.Setup(m => m.GetSkuCountsByRetailerVm()).Returns(new SkuCountByRetailerVm());
的方式mockFactory.Setup(m => m.GetSkuCountsByRetailerVm()).Returns(new SkuCountByRetailerVm());
the vm just points to the same object, so I would rather need to have it instantiate a new vm each time? vm 只是指向同一个对象,所以我宁愿每次都需要它实例化一个新的 vm? Not sure if this is correct conclusion and if so how to do it differently way with Moq.不确定这是否是正确的结论,如果是,如何使用 Moq 以不同的方式做到这一点。
I paste the test class below should this be needed.如果需要,我粘贴下面的测试类。
[TestInitialize]
public void Setup()
{
Mock<IReadingHelper> mockHelper = new Mock<IReadingHelper>();
Mock<IVmFactory> mockFactory = new Mock<IVmFactory>();
mockFactory.Setup(m => m.GetEmptyListOfSkuCountByRetailerVms()).Returns(new List<SkuCountByRetailerVm>());
mockFactory.Setup(m => m.GetSkuCountsByRetailerVm()).Returns(new SkuCountByRetailerVm());
mockHelper.Setup(m => m.GetAllRetailersInReading()).Returns(
new List<string> { "Fake1", "Fake2", "Fake3" });
mockHelper.Setup(m => m.GetSkuCountByRetailerInReading("Fake1")).Returns(5);
mockHelper.Setup(m => m.GetSkuCountByRetailerInReading("Fake2")).Returns(10);
mockHelper.Setup(m => m.GetSkuCountByRetailerInReading("Fake3")).Returns(15);
SkuCountByRetailerVmBuilder builder = new SkuCountByRetailerVmBuilder(mockHelper.Object, mockFactory.Object);
_vms = builder.GetSkuCountsByRetailer();
}
The Returns
method has lots of overloads. Returns
方法有很多重载。
Currently you are using the one with the signature Returns(TResult)
where you can specify the value to return and Moq use the same value every time the mocked method is called (so you get the same instance of your SkuCountByRetailerVm
.目前,您正在使用带有签名Returns(TResult)
那个,您可以在其中指定要返回的值,并且每次调用SkuCountByRetailerVm
方法时,Moq 都使用相同的值(因此您将获得SkuCountByRetailerVm
的相同实例。
You need to use one of the overloads which takes a Func<TResult>
as a parameter with this can you specify a function that will calculate the value to return from the method:您需要使用以Func<TResult>
作为参数的重载之一,您可以指定一个函数来计算从方法返回的值:
mockFactory.Setup(m => m.GetSkuCountsByRetailerVm())
.Returns(() => new SkuCountByRetailerVm());
With this setup you will get a different instance every time your mocked method is caled.使用此设置,每次调用模拟方法时,您都会获得不同的实例。
Also, you can implement the IClonable
Interface and use a special copy of the object whenever you want.此外,您可以实现IClonable
接口并IClonable
使用该对象的特殊副本。
mockFactory.Setup(m => m.GetSkuCountsByRetailerVm()) .Returns(() => (SkuCountByRetailerVm)yourIntance.Clone());
This is a good way to mock sequences for retry requests to networks or databases.这是模拟对网络或数据库的重试请求的序列的好方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.