Search code examples
c#rhino-mocks

Why does Rhino Mocks error on a stub, but not on the exact same thing as a mock?


I'm fairly new to rhino Mocks, just started using it this project.

I am testing some code which calls an external method to get an IEnumerable of 'Project', which I've got an interface for it so that I can stub/mock it out.

at the start of my unit test that tests some of the code that iterates over (or calls Count(), both cause the error) that IENumerable, I setup a stub implementation

IJobProcess stub = MockRepository.Stub<IJobProcess>();
SetupResult.For(stub.CheckTeamMeetingInLastMonth(null)).IgnoreArguments().Return(true);
SetupResult.For(stub.GetOutstandingActions(null)).IgnoreArguments().Return(
                    new List<ProjectActionsDomain.DomainObjects.ProjectAction>()
                    );      

This however results in:

PmqccFormTests.GetFlagsReturnsIncompleteFlagWhenIncomplete : FailedSystem.InvalidOperationException : Previous method 'IEnumerator.MoveNext();' requires a return value or an exception to throw.
at Rhino.Mocks.Impl.RecordMockState.AssertPreviousMethodIsClose()
at Rhino.Mocks.Impl.RecordMockState.MethodCall(IInvocation invocation, MethodInfo method, Object[] args)
at Rhino.Mocks.MockRepository.MethodCall(IInvocation invocation, Object proxy, MethodInfo method, Object[] args)
at Rhino.Mocks.Impl.RhinoInterceptor.Intercept(IInvocation invocation)
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at System.Linq.Enumerable.Count(IEnumerable`1 source)
at PmqccDomain.DomainObjects.PmqccForm.GetFlags() in PmqccForm.cs: line 387
at PmqccUnitTests.PmqccFormTests.GetFlagsReturnsIncompleteFlagWhenIncomplete() in PmqccFormTests.cs: line 426 

However, if I change this to

        IJobProcess mock = MockRepository.GenerateMock<IJobProcess>();

        mock.Expect(x => x.GetOutstandingActions(null)).IgnoreArguments().Return(
            new List<ProjectActionsDomain.DomainObjects.ProjectAction>());
        mock.Expect(x => x.CheckTeamMeetingInLastMonth(null)).IgnoreArguments().Return(true);

It does not error, I thought a stub was a mock that didn't assert on its results basically? or am I wrong there? What does Rhino Mocks do differently that avoids the error when using a mock?


Solution

  • As Jonny C has highlighted I believe that SetupResult is not compatible with MockRepository.GenerarteStub.

    SetupResult seemsed to be used with the expect-record and playback functionality that Rhino used before lamba expressions were used.

    The preferred way is to use the Arrange-Act-Assert syntax that was introduced later however when looking at the Rhino API it is hard to tell what to use for AAA.

    What I do is to only stub methods/properties that need to return a value and assert that methods were called at the end.

    so what should work is...

    //Arrange
    IJobProcess stub = MockRepository.GenerateStub<IJobProcess>();
    stub.Stub(x => x.CheckTeamMeetingInLastMonth(null)).IgnoreArguments().Return(true);
    stub.Stub(x => x.GetOutstandingActions(null)).IgnoreArguments().Return(
                    new List<ProjectActionsDomain.DomainObjects.ProjectAction>()
                    );   
    //Act
    -- Perform SUT --
    
    //Assert
    stub.AssertWasCalled(x => x.CheckTeamMeetingInLastMonth(someExpectedValue));
    

    useage of SetupResult

    usage of AAA