C# 如何确保Rhinomock中不再调用方法?

C# 如何确保Rhinomock中不再调用方法?,c#,unit-testing,rhino-mocks,C#,Unit Testing,Rhino Mocks,我有一个如下示例所示的代码: public interface IDependency { void Foo(); } public class MainClass{ Timer tmr = new Timer(100); IDependency dependency; public MainClass(IDependency dep) { dependency = dep; tmr.Elapsed += OnEla

我有一个如下示例所示的代码:

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
不再被调用进行单元测试

尝试使用
BackToRecord
ReplayAll
,但未能达到目标。调用
AssertWasNotCalled
不会在调用
Stop()
后失败


有什么方法可以达到同样的效果吗?

因为计时器的间隔是已知的,所以您可以等待设定的时间并计算计时器调用的次数
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();
}
[TestMethod]
公共异步任务MainClass\u应\u停止(){
//安排
var dependency=Substitute.For();
var subject=新的MainClass(依赖项);
var expectedDelay=200;
var-expectedCalls=2;
//表演
subject.Start();
等待任务。延迟(预期延迟);
subject.Stop();
等待任务。延迟(100);
//断言
Received(expectedCalls).Foo();
}
虽然上面使用了NSubstitute,但同样的方法也可以应用于您选择的模拟框架

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


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

在Nkosi回答之后,下面是如何使用Rhino Mock(另请参阅中的一些讨论):

[测试]
公共异步任务MainClass\u应\u停止(){
//安排
var dependency=MockRepository.GenerateMock();
var subject=新的MainClass(依赖项);
var expectedDelay=200;
var-expectedCalls=2;
//表演
subject.Start();
等待任务。延迟(预期延迟);
subject.Stop();
等待任务。延迟(100);
//断言
dependency.AssertWasCalled(
dependency=>dependency.Foo(),
options=>options.Repeat.Times(expectedCalls)
);
}

虽然这看起来还可以(尚未尝试),但我想要一种不依赖于计时器运行时间的方法。我想知道的是,一旦调用Stop,我们是否能够“清除”模拟的录制,然后确保该方法没有被调用。@PramodBR-如果不等待,您怎么知道该方法没有被调用?我假设一个测试应该至少等待一个计时器周期(可能是计时器周期+epsilon),以验证实际上没有调用…@Amittai Shapira我同意测试应该等待。但我希望避免依赖计时器的间隔。相反,我想检查在调用Stop方法后是否不调用该方法,而不依赖于内部实现细节。@PramodBR-我不确定您将如何做到这一点。。。让我们假设间隔为5分钟,在不等待的情况下调用Start(),然后调用Stop()。在这种测试中,断言没有调用该方法不会验证Stop()是否有效,因为该方法可能在测试完成后被调用。。。
[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)
  );
}