13

現在の日付/時刻の値を提供するTimeMachineクラスがあります。クラスは次のようになります。

public class TimeMachine
{
    public virtual DateTime GetCurrentDateTime(){ return DateTime.Now; };
    public virtual DateTime GetCurrentDate(){ return GetCurrentDateTime().Date; };
    public virtual TimeSpan GetCurrentTime(){ return GetCurrentDateTime().TimeOfDay; };
}

3 つのメソッドすべてをスタブ化する必要がないように、メソッドをスタブ化し、他の 2 つTimeMachineのメソッドがスタブ化されたメソッドを使用できるように、テストでスタブを使用したいと考えています。私は次のようにテストを書き込もうとしました:GetCurrentDateTimeGetCurrentDateTime

var time = MockRepository.GenerateStub<TimeMachine>();
time.Stub(x => x.GetCurrentDateTime())
    .Return(new DateTime(2009, 11, 25, 12, 0, 0));
Assert.AreEqual(new DateTime(2009, 11, 25), time.GetCurrentDate());

しかし、テストは失敗します。内部でスタブを使用する代わりにGetCurrentDate戻ります。default(DateTime)GetCurrentDateTime

そのような動作を実現するために使用できるアプローチはありますか、それとも現時点では理解できない RhinoMocks の基本的な概念的な機能ですか? これら 2 つのGetDate/メソッドを削除して/の使用Time法をインライン化できることはわかっていますが、これが可能かどうかを理解したいと思います。.Date.TimeOfDay

4

5 に答える 5

12

メソッドが としてマークされている場合、メソッドをvirtualスタブしていなくても、スタブは元のメソッドを呼び出しません。次のようにして、RhinoMocks に元のメソッドを強制的に呼び出すことができます。

var time = MockRepository.GenerateStub<TimeMachine>();
time.Stub(x => x.GetCurrentDateTime()).Return(new DateTime(2009, 11, 25, 12, 0, 0));

time.Stub(x => x.GetCurrentDate()).CallOriginalMethod(OriginalCallOptions.NoExpectation);

Assert.AreEqual(new DateTime(2009, 11, 25), time.GetCurrentDate());

これは、RhinoMocks に元の元のメソッドを呼び出させる 3 番目の (分離された) 行です。

于 2013-03-05T14:41:27.183 に答える
9

TimeMachineを抽象クラスに変更します。

public abstract class TimeMachine
{
    public abstract DateTime GetCurrentDateTime();
    public DateTime GetCurrentDate(){ return GetCurrentDateTime().Date; };
    public TimeSpan GetCurrentTime(){ return GetCurrentDateTime().TimeOfDay; };
}

TimeMachine本番環境では、次のような具体的な実装を作成できます。

public class SystemTimeMachine : TimeMachine
{
    public override DateTime GetCurrentDateTime()
    {
        return DateTime.Now;
    }
}

消費するすべてのクラスTimeMachineに抽象化を注入できるようになりましたが、実稼働環境ではオブジェクト グラフをSystemTimeMachine.

于 2009-11-25T15:42:59.240 に答える
4

これら 2 つのメソッドで virtual を使用しないことでこれを実現できることがわかりました。これにより、スタブの生成時にメソッドがオーバーライドされるのを防ぐことができます。

public class TimeMachine
{
    public virtual DateTime GetCurrentDateTime(){ return DateTime.Now; };
    public DateTime GetCurrentDate(){ return GetCurrentDateTime().Date; };
    public TimeSpan GetCurrentTime(){ return GetCurrentDateTime().TimeOfDay; };
}

これでテストはパスします。

于 2009-11-25T15:49:20.667 に答える
1

スタブは、メソッドとプロパティの呼び出しに対する既定の応答を提供するだけで、TimeMachine の実際の実装については何も知りません。残念ながら、3 つの方法のそれぞれ (またはテストしたい特定の方法) の結果を設定する必要があります。

于 2009-11-25T15:40:57.080 に答える
1

使用している Rhino.Mocks のバージョンはわかりませんが、GetCurrentDateTime() メソッドのみを仮想化し (以前のポスターが提案したように)、PartialMock() を使用してモック オブジェクトを作成します。設定方法はたくさんありますが、次の方法でうまくいくはずです。

var mocks = new MockRepository();
var time = mocks.PartialMock<TimeMachine>();
using (mocks.Record())
{
   Expect.Call(time.GetCurrentDateTime()).Return(new DateTime(2009, 11, 25, 12, 0, 0));
}
using (mocks.Playback())
{
   Assert.AreEqual(new DateTime(2009, 11, 25), time.GetCurrentDate());
}
于 2009-11-25T19:43:25.747 に答える