Moq - 模拟工厂不会在每次迭代时生成新对象
Moq - mocking factory not generating new object with each iteration
我正在尝试最小起订量并测试以下方法:
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;
}
SkuCountByRetailerVm class 是非常基本的数据传输对象,它具有 Retailer 和 SkuCount 属性。
测试中的 class 依赖于 IFactory 和 IHelper,我在测试中模拟了这两个 class。
看起来 class 测试中的代码没问题。模拟时的问题是我将 3 个相同的视图模型添加到列表中(都像我希望添加的最后一个),而不是 3 个不同的视图模型。我认为我的测试的问题是我设置工厂最小起订量的方式 mockFactory.Setup(m => m.GetSkuCountsByRetailerVm()).Returns(new SkuCountByRetailerVm());
vm 只是指向同一个对象,所以我宁愿每次都需要让它实例化一个新的 vm?不确定这是否是正确的结论,如果是,如何使用 Moq 以不同的方式进行。
如果需要,我会在下面粘贴测试 class。
[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();
}
Returns
method 有很多重载。
目前您正在使用带有签名 Returns(TResult)
的签名,您可以在其中指定 return 的值,并且 Moq 每次调用模拟方法时都使用相同的值(因此您得到相同的值SkuCountByRetailerVm
.
的实例
您需要使用一个带有 Func<TResult>
as a parameter 的重载,您能否指定一个函数来计算方法 return 的值:
mockFactory.Setup(m => m.GetSkuCountsByRetailerVm())
.Returns(() => new SkuCountByRetailerVm());
使用此设置,每次调用模拟方法时都会获得不同的实例。
此外,您可以实现 IClonable
接口并在需要时使用对象的特殊副本。
mockFactory.Setup(m => m.GetSkuCountsByRetailerVm())
.Returns(() => (SkuCountByRetailerVm)yourIntance.Clone());
这是模拟重试网络或数据库请求序列的好方法。
我正在尝试最小起订量并测试以下方法:
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;
}
SkuCountByRetailerVm class 是非常基本的数据传输对象,它具有 Retailer 和 SkuCount 属性。
测试中的 class 依赖于 IFactory 和 IHelper,我在测试中模拟了这两个 class。
看起来 class 测试中的代码没问题。模拟时的问题是我将 3 个相同的视图模型添加到列表中(都像我希望添加的最后一个),而不是 3 个不同的视图模型。我认为我的测试的问题是我设置工厂最小起订量的方式 mockFactory.Setup(m => m.GetSkuCountsByRetailerVm()).Returns(new SkuCountByRetailerVm());
vm 只是指向同一个对象,所以我宁愿每次都需要让它实例化一个新的 vm?不确定这是否是正确的结论,如果是,如何使用 Moq 以不同的方式进行。
如果需要,我会在下面粘贴测试 class。
[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();
}
Returns
method 有很多重载。
目前您正在使用带有签名 Returns(TResult)
的签名,您可以在其中指定 return 的值,并且 Moq 每次调用模拟方法时都使用相同的值(因此您得到相同的值SkuCountByRetailerVm
.
您需要使用一个带有 Func<TResult>
as a parameter 的重载,您能否指定一个函数来计算方法 return 的值:
mockFactory.Setup(m => m.GetSkuCountsByRetailerVm())
.Returns(() => new SkuCountByRetailerVm());
使用此设置,每次调用模拟方法时都会获得不同的实例。
此外,您可以实现 IClonable
接口并在需要时使用对象的特殊副本。
mockFactory.Setup(m => m.GetSkuCountsByRetailerVm())
.Returns(() => (SkuCountByRetailerVm)yourIntance.Clone());
这是模拟重试网络或数据库请求序列的好方法。