【问题标题】:Moq setup causing null起订量设置导致 null
【发布时间】:2016-10-21 04:57:00
【问题描述】:

我是单元测试和起订量的新手,所以如果我的方法或理解完全错误,请帮助我。

我有一个正在测试的逻辑方法。我已经注释掉了逻辑,但它所做的只是检查“模型”中的一些值,如果有问题就返回。在我们正在研究的情况下,没有问题。

        public ReplyDto SaveSettings(SnowballDto model)
        {

            // Some logic here that reads from the model.

            var result = _data.SaveSettings(model);
            return result;
        }

我的测试,使用 NUnit 和 MOQ,如下所示:

_logic = new SnowballLogic(mockSnowballData.Object, mockLog.Object);

           mockSnowballData
                .Setup(x => x.SaveSettings(SnowballDto_Good))
                .Returns(new ReplyDto {
                    IsSuccess = true,
                    Message = "Saved",
                    ReplyKeyID = 1
                });

在每次测试中,我都会调用一个私有设置函数来设置我将要使用的东西。

 private void SetupData()
        {
            SnowballDto_Good = new SnowballDto {
                FirstPaymentDate = DateTime.UtcNow,
                ID = 1,
                OrderedIDPriority = new List<int>(),
                SnowballTypeID = 1,
                TargetPayment = 1000
            };

            DebtDtoList_ThreeDebt.Clear();
            DebtDtoList_ThreeDebt.Add(new DebtDto { ID = 1, Description = "Debt 1", ManualSnowballPriority = 1, MinimumMonthlyPaymentAmount = 140, OpeningBalance = 5000, RunningData = new DebtRunningDto { Balance = 5000 }, OpeningDate = DateTime.UtcNow, SnowballID = 1, StandardRate = 10 });
            DebtDtoList_ThreeDebt.Add(new DebtDto { ID = 2, Description = "Debt 2", ManualSnowballPriority = 2, MinimumMonthlyPaymentAmount = 90, OpeningBalance = 1600, RunningData = new DebtRunningDto { Balance = 1600 }, OpeningDate = DateTime.UtcNow, SnowballID = 1, StandardRate = 15 });
            DebtDtoList_ThreeDebt.Add(new DebtDto { ID = 3, Description = "Debt 3", ManualSnowballPriority = 3, MinimumMonthlyPaymentAmount = 300, OpeningBalance = 9000, RunningData = new DebtRunningDto { Balance = 9000 }, OpeningDate = DateTime.UtcNow, SnowballID = 1, StandardRate = 20 });


        }

所以,我对 MOQ 的理解是,“当调用 SnowballData 类的“SaveSettings”方法并传入“SnowballDto_Good”对象时,总是返回一个 IsSuccess = true 的新 ReplyDto。

因此,当我拨打电话时:

var result = _data.SaveSettings(model);

它应该返回带有 IsSuccess = true 的 ReplyDto

但是,当我在调用“SaveSettings”时设置断点时,它始终返回 null。

如果我将设置更改为:

.Setup(x => x.SaveSettings(It.IsAny<SnowballDto>()))

测试通过。为什么当我给它一个真正的 SnowballDto 时它返回 null?

【问题讨论】:

  • 它通过引用比较参数
  • 您传递的对象是否与设置中使用的对象相同?
  • 我们必须看到更多。 SnowballDto_Good 实例在哪里创建。 SnowballDto 类型是否覆盖 Equals(object),如果是,如何?另外,显示足够的代码来说服我们这是SnowballDto 的同一个实例。记住 Setup 中的 lambda 转换为表达式树时的闭包语义。
  • 但是 one new SnowballDto { FirstPaymentDate = DateTime.UtcNow, ID = 1, OrderedIDPriority = new List&lt;int&gt;(), SnowballTypeID = 1, TargetPayment = 1000 } 是否等于 另一个 new SnowballDto { FirstPaymentDate = DateTime.UtcNow, ID = 1, OrderedIDPriority = new List&lt;int&gt;(), SnowballTypeID = 1, TargetPayment = 1000 }?答案取决于类 SnowballDto 是否覆盖 Equals(object) 以及如何覆盖。最可能的解释是设置没有“满足”,因为参数不被认为是匹配的。 loose 模拟只会返回 null 没有设置匹配。
  • 另外,DateTime.UtcNow 的两次读取不会给出相同的值。时间流逝;下次你请求“现在”时,可能已经过了几微秒,“现在”会改变。

标签: c# unit-testing nunit moq


【解决方案1】:

好吧,您似乎在测试的“行为”部分传递了一个名为 modelSnowballDto 实例

var result = _data.SaveSettings(model);

然而,在 moq 的设置中,您将其配置为仅当实例 SnowballDto_Good 指定为 SaveSettings 时才返回新的 ReplyDto。在所有其他情况下,方法的模拟未配置,并且 - 在松散模拟策略(默认)的情况下 - 它将返回 SaveSettings 返回类型的默认值。在这种情况下:null。

当您使用 It.IsAny&lt;SnowballDto&gt; 时,您基本上是在告诉 moq 配置 SaveSettings 以返回一个新实例,然后不仅将实例 SnowballDto_Good 传递给它,而且该类型的任何实例都传递给它。

你需要做的是改变你的测试中的“行为”部分,如下所示:

var result = _data.SaveSettings(SnowballDto_Good);

那么它将与您的原始模拟设置一起使用,因为正确的实例将被传递给SaveSettings

这正是我喜欢使用 MockBehavior.Strict 实例化我的模拟的原因。

它不会返回 null,而是会抛出一个异常,告诉你没有正确配置你的 mock。

希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-26
    • 1970-01-01
    • 2010-11-30
    • 2019-08-19
    • 2010-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多