2

我有以下代码:

public class Weather
{
    public int Temperature { get; set; }
    public string Description { get; set; }
}

public class WeatherProvider
{
    public virtual Weather GetWeather()
    {
        var w = new Weather();
        var hour = Hour;
        if (hour < 5)
        {
            w.Description = "Sunny";
            w.Temperature = 12;
        }
        else if (hour < 12)
        {
            w.Description = "Windy";
            w.Temperature = 18;
        }
        else
        {
            w.Description = "Snow";
            w.Temperature = 2;
        }
        return w;
    }

    public virtual int Hour
    {
        get { return DateTime.Now.Hour; }
    }
}

var mockWeatherProvider = new Moq.Mock<WeatherProvider>(MockBehavior.Loose);
mockWeatherProvider.SetupGet(x => x.Hour).Returns(2);

var actualWeather = mockWeatherProvider.Object.GetWeather();//This line always returns null? WHY???
mockWeatherProvider.Verify(x=>x.GetWeather());

任何人都可以解释为什么行 var actualWeather = mockWeatherProvider.Object.GetWeather() 返回 null 吗?我实际上希望调用真正的方法。我怎样才能做到这一点?

4

4 回答 4

6

您尚未为该GetWeather()方法设置行为。基本上,你在这里做什么

var mockWeatherProvider = new Moq.Mock<WeatherProvider>(MockBehavior.Loose);

正在创建一个看起来像 WeatherProvider的空对象。你必须告诉你想要使用的mockWeatherProvider每个方法和属性应该为你做什么


编辑,因为我意识到你可能真正想要什么

如果您试图模拟基本上只有一半课程的内容,那么在这种特殊情况下,您将以错误的方式进行实施。例如,如果您想模拟Hour返回的内容,则可以WeatherProvider通过某些TimeProvider实现或某些WeatherProvider依赖于的实现将该属性提供给该属性。

var mockedTimeProvider = new Moq.Mock<TimeProvider>(MockBehavior.Loose);
mockedTimeProvider.SetupGet(p => p.Hour).Returns(2);

var weatherProvider = new WeatherProvider(mockedTimeProvider.Object);
var actualWeather = weatherProvider.GetWeather();

再次编辑

尝试将您GetWeather()的设置为非虚拟,然后使用存根而不是完全模拟来生成模拟。这应该防止该方法被默认返回器覆盖。但是,这种方式会使您的设计有些混乱,并且不会像上面那样使事情变得清晰。关注点分离等等。=)

于 2012-08-08T14:25:43.810 回答
3

通过使用松散的模拟,您将获得所有虚拟属性和方法的默认值。您想使用 CallBase 告诉 Moq 故障恢复到正常实现。

尝试这个:

var mockWeatherProvider = new Moq.Mock<WeatherProvider>(MockBehavior.Loose) { CallBase = true };
mockWeatherProvider.SetupGet(x => x.Hour).Returns(2);
于 2012-08-21T15:28:11.707 回答
1

您的模拟没有指定 GetWeather 调用的实现。由于您是在模拟对象而不是您的具体实现上进行操作,因此 Moq 将返回默认值。在这种情况下,默认值为 null。

如果您想测试实现,您应该只使用具体实现并在该对象上设置 Hour 的行为。这将允许您练习已实现的代码并验证其行为。

于 2012-08-08T14:27:44.760 回答
0

尝试

var mockWeatherProvider = new Moq.Mock<WeatherProvider>(MockBehavior.Normal);
于 2012-08-08T14:30:34.037 回答