繁体   English   中英

Moq - 如何模拟属性但允许在C#中进行方法调用?

[英]Moq - How to mock a property but allow method calls in C#?

我有以下代码:

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? 我实际上想要调用真正的方法。 我怎么能得到这个?

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

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

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


编辑,因为我意识到你可能真正想要的东西

如果你试图模拟的只是你班级的一半,那么在这种特殊情况下你会以错误的方式进行实施。 如果你想模拟,比如说什么Hour返回,你可以通过一些TimeProvider实现或WeatherProvider依赖的一些属性向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()设置为非虚拟,然后使用存根而不是完全模拟来生成模拟。 这应该保持方法不被默认返回者覆盖。 虽然,这种方式会使你的设计有点尴尬,而不是像上面那样清楚。 分离关注,等等。 =)

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

尝试这个:

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

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

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

尝试

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM