views:

27

answers:

2

Hello,

in order to test another class, I want to create a stub for an interface IFoo:

public interface IFoo
{
    int DoSomething(int value);
}

The stub is created in the SetUp (or TestInitialize)-method for the test fixture and stored in a property as almost all test methods need an IFoo:

this.Foo = MockRepository.GenerateStub<IFoo>();

As IFoo.DoSomething needs just to return the passed value in all cases except one I added this behavior to my SetUp method:

this.Foo.Stub(f => f.DoSomething(0)).IgnoreArguments().Return(0).WhenCalled(mi => mi.ReturnValue = mi.Arguments[0]);

Now, however, this one test requires different behavior: Rather than returning the passed argument, a constant should be returned if the passed value equals another constant. The following approach (written in the test method itself) does not work:

this.Foo.Stub(f => f.DoSomething(42)).Return(43);

The previous specified, more general stub seems to override the more specific stub.
Is there any way to specify both specific and general stubs on RhinoMock-objects?

One workaround would be recreating the stub in the test-method itself - a duplication I would like to avoid. I could live with this version, however.
What I also do not want is a explicit exclusion of the "42" in the general statement via Constraints as this will effect the other tests negatively.
Calling BackToRecord is also not an option as it seems to reset other stubs, too.

Thanks for your answers!

+1  A: 

I don't think its possible to "reset" expectations. In this case I would avoid setting up this mock in the set up, instead I would create a method to easily set it up and call it from every test:

private IFoo SetUpFoo()
{
  IFoo foo = MockRepository.GenerateStub<IFoo>();
  foo.Stub(f => f.DoSomething(0)).IgnoreArguments().Return(0).WhenCalled(mi => mi.ReturnValue = mi.Arguments[0]);
}

Then just use this method in every test that needs the standard foo:

[Test]
public void StandardTest()
{
  IFoo foo = SetUpFoo();
  ...
}

in your special case you have to create foo manually and set up the expectation:

[Test]
public void SpecialTest()
{
  IFoo foo = MockRepository.GenerateStub<IFoo>();
  foo.Stub(f => f.DoSomething(42)).Return(43);
  ...
}

Of course you get some code duplication, but at least its clear which expectations are used in which test.

Grzenio
Well - that's very similar to what I meant with "One workaround would be recreating the stub in the test-method itself". I only wondered whether you can realize this without workarounds like those. It seems like RhinoMocks does not provide a mechanism like that.
winSharp93
A: 

I just found the solution to actually "override" stubs / expectations: Rhino Mocks: How to clear previous expectations on an object?

Applied to my problem I can now write:

this.Foo.Stub(f => f.DoSomething(42)).Return(43).Repeat.Any();

The documentation to Any says:

Repeat the method any number of times. This has special affects in that this method would now ignore orderring.

So this seems to be neither a bug or an undocumented feature.

winSharp93