如何断言方法只被调用一次?

时间:2011-09-09 23:11:06

标签: c# mocking rhino-mocks mspec fakeiteasy

[Subject(typeof(OnceADayProcessor))]
public class When_processing_process_twice
{
    private static ICanBeProcessedOnceADay ProcessedOnceADay;

    private Establish context = () => { OnceADayProcessor.Now = () => new DateTime(2011, 1, 1, 0, 0, 0, 0); };

    private Because of = () =>
                             {
                                 ProcessedOnceADay = MockRepository.GenerateMock<ICanBeProcessedOnceADay>();
                                 ProcessedOnceADay.Process();
                                 ProcessedOnceADay.Process();
                             };

    private It should_execute = () => ProcessedOnceADay.AssertWasCalled(x => x.Expect(p => p.Process()));
    private It should_execute_only_once = () => ProcessedOnceADay.AssertWasNotCalled(x => x.Expect(p => p.Process()));
}

已编辑的解决方案:

[Subject(typeof(OnceADayProcessor))]
public class When_processing_a_process_twice_at_the_same_day
{
    static ICanBeProcessedOnceADay canBeProcessedOnceADay;

    Establish context = () =>
    {
        canBeProcessedOnceADay = A.Fake<ICanBeProcessedOnceADay>();
    };

    Because of = () =>
    {
        OnceADayProcessor.Process(canBeProcessedOnceADay);
        OnceADayProcessor.Process(canBeProcessedOnceADay);
    };

    It should_execute_only_once = () => 
        A.CallTo(() => canBeProcessedOnceADay.Process()).MustHaveHappened(Repeated.Exactly.Once);
}

3 个答案:

答案 0 :(得分:4)

var mock = MockRepository.GenerateMock<ICanBeProcessedOnceADay>();
mock.Expect(a => a.Process()).Repeat.Times(1);
...
mock.VerifyAllExpectations();

答案 1 :(得分:4)

我会将stub.Expect()stub.VerifyAllExpectations()的来电替换为stub.AssertWasCalled(x => x.Process(), o => o.Repeat.Once())中的It。如果您对存根有多个期望,则可以将每个断言放在一个It中,并让它们彼此独立地失败(或成功)。

存根的创建将进入Establish(基本上,创建任何依赖项和被测系统是单元测试中“排列”阶段的一部分)。

另外,请考虑不要使用GenerateMockGenerateStub,因为当您调用除Expect指定的方法之外的其他方法时,模拟可能会导致严格的测试。像FakeItEasy这样的图书馆通常提供更好,更易被发现的API,更容易学习,并且会让你陷入“成功的陷阱”。

答案 2 :(得分:3)

如果你想确保一个方法只被调用一次,你需要一个严格的模拟:

var mock = MockRepository.GenerateStrictMock<IShouldOnlyBeCalledOnce>();
mock.Expect(a => a.Process()).Repeat.Once();

sut.Process(mock)

mock.VerifyAllExpectations();

如果您只是使用GenerateMock,它将执行&#34;至少&#34;校验。这也适用于Repeats.Times(x)。