15

Can anyone tell me why in the world the following test is not failing?

[Test]
public void uhh_what() {
    var a = MockRepository.GenerateMock<IPrebuiltNotifier>();
    a.Expect(x => x.Notify()).Repeat.Once();
    a.Notify();
    a.Notify();
    a.VerifyAllExpectations();
}

Really need a second pair of eyes to confirm I'm not crazy...now I'm worried that all my tests are unreliable.

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
George Mauer
  • 117,483
  • 131
  • 382
  • 612
  • 1
    For future reference ([albeit Rhino mock is old](https://github.com/ayende/rhino-mocks)) I add that 'Stub'-'Once'-'VerifyAllExpectations' as in `mock.Stub(x => x.Notify()).Repeat.Once();` also does not work as expected. Instead [`AssertWasCalled`](https://benbiddington.wordpress.com/2009/06/23/rhinomocks-repeat-times/) should be used. – LosManos Jan 23 '19 at 09:41

2 Answers2

27

There is already a thread on the RhinoMocks group.

GenerateMock creates a dynamic mock. The dynamic mock allows calls that are not specified (=expected). If this happens, it just returns null (or the default value of the return type).

Note: Repeat is a specification of the behaviour (like Stub), not the expectation even if specified in an expectation.

If you want to avoid having more then a certain number of calls, you could write:

[Test]
public void uhh_what() 
{
    var a = MockRepository.GenerateMock<IPrebuiltNotifier>();
    a.Expect(x => x.Notify()).Repeat.Once();
    a.Stub(x => x.Notify()).Throw(new InvalidOperationException("gotcha"));
    a.Notify();

    // this fails
    a.Notify();

    a.VerifyAllExpectations();
}

Or

[Test]
public void uhh_what() 
{
    var a = MockRepository.GenerateMock<IPrebuiltNotifier>();
    a.Notify();
    a.Notify();

    // this fails
    a.AssertWasCalled(
      x => x.Notify(), 
      o => o.Repeat.Once());
}
Stefan Steinegger
  • 63,782
  • 15
  • 129
  • 193
  • 1
    oh! I didn't know that AssertWasCalled had a second argument where you could do more specifications, this changes everything! – George Mauer May 20 '09 at 12:17
  • 1
    It is the same issue with PartialMock, if you ever step on it. – Dennis Sep 13 '11 at 13:20
  • 1
    The first solution (where you throw an exception) _will_ make the test fail if `Notify` is called more than once. However, if it's only called once (at least that's what I assume the code under test should do), the test won't pass as it should because it's expecting a _second_ call to `Notify` that never comes. Set up `a.Expect(x => x.Notify()).Repeat.Once()` followed by `a.Stub(x => x.Notify()).Throws(...)` to do the job. – geoffmazeroff Sep 27 '11 at 19:55
  • @geoffmazeroff: you are right. This answer exists for more than 2 years and nobody ever recognized it ... Thanks, I fix it. – Stefan Steinegger Sep 28 '11 at 14:13
9

When using GenerateMock (or with Dynamic Mocks in general) I always mentally insert the following:

a.Expect(x => x.Notify()).Repeat.*[AtLeast]*Once();

Sam Shiles
  • 10,529
  • 9
  • 60
  • 72