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提供することができます。WeatherProviderTimeProviderWeatherProvider

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()仮想として設定してから、完全なモックの代わりにスタブを使用してモックを生成してください。これにより、メソッドがデフォルトの returner でオーバーライドされないようにする必要があります。ただし、この方法では設計が少し混乱し、上記のように明確にはなりません。関心の分離など。=)

于 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 に答える