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.开发者_如何学GoMoveNext();' 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?
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
I'm not sure exactly how SetupResult.For is used, but to stub a method I would normally use
stub.Stub(j => j.CheckTeamMeetingInLastMonth(null))
.IgnoreArguments().Return(true);
to do the same thing you're trying to do. mock.Stub() works for the same purpose too.
One thing to note is that the counterpart to
IJobProcess mock = MockRepository.GenerateMock<IJobProcess>();
is
IJobProcess stub = MockRepository.GenerateStub<IJobProcess>();
So to compare directly you might want to try stubbing that way and see if you get the error using the same syntax.
But to answer your question, yeah that's what a stub is, I don't know why that's failing (although I'm not familiar with the stub syntax you used). There's a similar bug discussed on a mailing list here, could be related to that.
精彩评论