开发者

Rhino Mocks: Minimal times to call seems not to work

开发者 https://www.devze.com 2023-02-09 17:58 出处:网络
Im using Rhino-Mocks 3.6 as mocking framework in my unit tests and have a problem with Repeat.Times():

Im using Rhino-Mocks 3.6 as mocking framework in my unit tests and have a problem with Repeat.Times():

I want to verify that a method on my mocked object is called exactly three times. According to the docs i should use Repeat.Times(3) or Repeat.Times(3, 3).

But what i observe is that its verifying for at least three calls, so when i call the method four times, my test still passes. It fails when calling the method only two times.

Here is my code. Is there anything wrong with it?

        MockRepository mocks = new MockRepository();
        IJobServiceEvent mo开发者_运维问答ckedJSE;
        using (mocks.Record())
        {
            mockedJSE = mocks.DynamicMock<IJobServiceEvent>();
            Expect.Call(() => mockedJSE.TransactionListChanged(null))
                .Repeat.Times(3);
        }

        using (mocks.Playback())
        {
            mockedJSE.TransactionListChanged(null);
            mockedJSE.TransactionListChanged(null);
            mockedJSE.TransactionListChanged(null);
            mockedJSE.TransactionListChanged(null);
        }


You need to use a StrictMock. A DynamicMock will allow methods calls that aren't expected. So your call to your method is expected three times (which happens). But when it happens a fourth time, it's not an error since you defined it as a DynamicMock (unexpected calls are allowed).

However, in the long run, using StrickMock can be a maintenance headache since your test knows too much about how the object is written (since you have to mock/stub every possible call that may be made).

I would recommend the AAA (Arrange, Act, Assert) syntax for your unit tests. Your test above could be written using a Stub, but still enforce the 3-limit call on your method:

IJobServiceEvent mockedJSE = MockRepository.GenerateStub<IJobServiceEvent>();

mockedJSE.TransactionListChanged(null);
mockedJSE.TransactionListChanged(null);
mockedJSE.TransactionListChanged(null);
mockedJSE.TransactionListChanged(null);

mockedJSE.AssertWasCalled(s => s.TransactionListChanged(null), o => o.Repeat.Times(3, 3));

UPDATE

To make sure only calls with certain args were made (although I do think this is basically a strict mock which can become a maintenance headache), use the arg constraints option three times to make sure those calls are made. Then have a final "AssertWasCalled" that ignores the arguments and make sure it only was called three times:

mockedJSE.AssertWasCalled(s => s.TransactionListChanged(null), o => o.IgnoreArguments().Repeat.Times(3, 3));
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号