Stub一个类的方法,让其他真正的方法使用这个stubbed方法

But*_*aur 13 c# rhino-mocks mocking stub

我有一个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; };
}
Run Code Online (Sandbox Code Playgroud)

我想TimeMachine在我的测试中使用存根,以便我只是存根GetCurrentDateTime方法,让其他两个方法使用存根GetCurrentDateTime方法,这样我就不必存根这三种方法.我试着像这样编写测试:

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());
Run Code Online (Sandbox Code Playgroud)

但测试失败了.GetCurrentDate返回default(DateTime)而不是在GetCurrentDateTime内部使用存根.

有没有什么方法可以用来实现这样的行为,还是只是RhinoMocks的一些基本概念特征,我现在还没有抓住?我知道我可以摆脱这两个GetDate/ Time方法并内联.Date/ .TimeOfDay用法,但我想知道这是否可行.

Pet*_*ter 11

如果方法被标记为virtual,即使您没有使用Stub方法,Stub也不会调用原始方法.您可以通过执行以下操作强制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());
Run Code Online (Sandbox Code Playgroud)

这是第三条(分离的)线,使RhinoMocks调用底层的原始方法.


Mar*_*ann 9

将您更改TimeMachine为抽象类:

public abstract class TimeMachine
{
    public abstract DateTime GetCurrentDateTime();
    public DateTime GetCurrentDate(){ return GetCurrentDateTime().Date; };
    public TimeSpan GetCurrentTime(){ return GetCurrentDateTime().TimeOfDay; };
}
Run Code Online (Sandbox Code Playgroud)

出于生产目的,您可以创建如下的具体实现TimeMachine:

public class SystemTimeMachine : TimeMachine
{
    public override DateTime GetCurrentDateTime()
    {
        return DateTime.Now;
    }
}
Run Code Online (Sandbox Code Playgroud)

所有消耗的类TimeMachine现在都可以注入抽象,但在生产中你可以用你的对象图连接SystemTimeMachine.


But*_*aur 4

我刚刚发现可以通过在这两种方法上不使用 virtual 来实现此目的 - 它可以保护这些方法在生成存根时不被覆盖。

public class TimeMachine
{
    public virtual DateTime GetCurrentDateTime(){ return DateTime.Now; };
    public DateTime GetCurrentDate(){ return GetCurrentDateTime().Date; };
    public TimeSpan GetCurrentTime(){ return GetCurrentDateTime().TimeOfDay; };
}
Run Code Online (Sandbox Code Playgroud)

现在测试通过了。

  • 这可能会使测试通过,但只有当该类旨在充当基类并且该方法专门设计为可重写时,才应将方法设为虚拟。不应该仅仅为了单元测试而将其虚拟化。 (3认同)