【问题标题】:How to ensure that a method is not called anymore in RhinoMocks?如何确保不再调用 RhinoMocks 中的方法?
【发布时间】:2019-06-26 15:10:10
【问题描述】:

我的代码如下所示:

public interface IDependency
{
    void Foo();
}


public class MainClass{

    Timer tmr = new Timer(100);
    IDependency dependency;

    public MainClass(IDependency dep)
    {
        dependency = dep;
        tmr.Elapsed += OnElapsed;
    }

    void OnElapsed(object sender, EventArgs e)
    {
        dependency.Foo();
    }

    public void Start()=> tmr.Start();
    public void Stop() => tmr.Stop();

}

使用 RhinoMock 和/或 nunit,我想进行单元测试,一旦调用 'Stop',IDependency.Foo 将不再被调用

尝试使用BackToRecordReplayAll,但无法达到目标。调用Stop() 后调用AssertWasNotCalled 不会失败。

有没有办法达到同样的效果?

【问题讨论】:

    标签: c# unit-testing rhino-mocks


    【解决方案1】:

    由于定时器的间隔是已知的,你可以等待一个设定的时间,然后计算定时器调用了多少次Foo

    例如

    [TestMethod]
    public async Task MainClass_Should_Stop() {
        //Arrange
        var dependency = Substitute.For<IDependency>();
        var subject = new MainClass(dependency);
        var expectedDelay = 200;
        var expectedCalls = 2;
    
        //Act
        subject.Start();
        await Task.Delay(expectedDelay);
        subject.Stop();
        await Task.Delay(100);
    
        //Assert
        dependency.Received(expectedCalls).Foo();
    }
    

    虽然上面使用了 NSubstitute,但同样可以应用于您选择的模拟框架。

    如果我将预期延迟更改为会导致预期调用不同的延迟,那么测试将失败。

    例如,当延迟设置为 100 毫秒并且呼叫保持在 2 时,它会失败,因为只会发生一次呼叫。

    【讨论】:

    • 虽然这看起来不错(还没有尝试过),但我想要一种不依赖于计时器经过时间的方法。我正在寻找的是我们是否可以在调用 Stop 后“清除”模拟的录音,然后确保不会调用该方法。
    • @PramodBR - 你怎么知道没有等待就不会调用该方法?我假设测试应该至少等待定时器周期(可能还有定时器周期 + epsilon),以验证实际上没有调用......
    • @Amittai Shapira 我同意测试应该等待。但我想避免取决于计时器的间隔。相反,我想检查是否在调用 Stop 方法之后不调用该方法,而不依赖于内部实现细节。
    • @PramodBR - 我不知道你会怎么做......让我们假设间隔是 5 分钟,你调用 Start() 然后 Stop() 没有等待。在这样的测试中,断言该方法未被调用并不能验证 Stop() 是否有效,因为该方法可能在测试完成后被调用......
    【解决方案2】:

    按照 Nkosi 的回答,下面是您使用 Rhino Mocks 的方法(另请参阅 this question 中的一些讨论):

    [Test]
    public async Task MainClass_Should_Stop() {
        //Arrange
        var dependency = MockRepository.GenerateMock<IDependency>();
        var subject = new MainClass(dependency);
        var expectedDelay = 200;
        var expectedCalls = 2;
    
        //Act
        subject.Start();
        await Task.Delay(expectedDelay);
        subject.Stop();
        await Task.Delay(100);
    
        //Assert
        dependency.AssertWasCalled(
          dependency => dependency.Foo(),
          options => options.Repeat.Times(expectedCalls)
      );
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多