【问题标题】:Moq - mocking factory not generating new object with each iterationMoq - 模拟工厂不会在每次迭代时生成新对象
【发布时间】:2016-04-16 17:54:49
【问题描述】:

我正在尝试最小起订量并测试以下方法:

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 类是非常基本的数据传输对象,它具有 Retailer 和 SkuCount 属性。

被测类依赖于 IFactory 和 IHelper,我在测试类中对它们进行了模拟。

看起来被测类的代码没问题。模拟时的问题是我将 3 个相同的视图模型添加到列表中(都像我希望添加为最后一个的视图模型),而不是 3 个不同的视图模型。我认为我的测试的问题是我设置工厂的最小起订量mockFactory.Setup(m =&gt; m.GetSkuCountsByRetailerVm()).Returns(new SkuCountByRetailerVm()); vm 只是指向同一个对象,所以我宁愿每次都需要它实例化一个新的 vm?不确定这是否是正确的结论,如果是,如何以不同的方式使用 Moq。

如果需要,我在下面粘贴测试类。


[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();
}

【问题讨论】:

    标签: c# unit-testing moq mstest


    【解决方案1】:

    Returns method 有很多重载。

    目前您正在使用带有签名 Returns(TResult) 的那个,您可以在其中指定要返回的值,并且 Moq 每次调用模拟方法时都使用相同的值(因此您会得到相同的 SkuCountByRetailerVm 实例。

    您需要使用采用Func&lt;TResult&gt; as a parameter 的重载之一,您可以指定一个函数来计算从该方法返回的值:

    mockFactory.Setup(m => m.GetSkuCountsByRetailerVm())
               .Returns(() => new SkuCountByRetailerVm());
    

    使用此设置,每次调用模拟方法时都会获得不同的实例。

    【讨论】:

      【解决方案2】:

      此外,您可以实现IClonable 接口,并随时使用该对象的特殊副本。

      mockFactory.Setup(m => m.GetSkuCountsByRetailerVm())
                 .Returns(() => (SkuCountByRetailerVm)yourIntance.Clone());

      这是模拟对网络或数据库的重试请求序列的好方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-07
        • 1970-01-01
        • 2015-06-30
        • 2018-07-07
        相关资源
        最近更新 更多