views:

37

answers:

3

Sometimes I stub dependencies in test class setup and then want to restub some of them in concrete test. But Rhino mocks remembers only the first stub value and it is a bit inconvenient.

someStub.Stub(x => x.SomeMethod(1)).Return(100);
var value1 = someStub.SomeMethod(1);
someStub.Stub(x => x.SomeMethod(1)).Return(200);
var value2 = someStub.SomeMethod(1);

value 2 will be equal to 100.

Is it a designed behaviour? Are there any workarounds?

A: 

You can work around it with inheritance. If you have a base test class and some test subclasses that run the tests, you can make the return value a protected property of the base test class, and set the value in the subclasses at a point before base. Initialize is called. So (using MSTEST) you could have:

in your base class:

protected int ReturnVal{get; set;}

public void Init()
{
someStub = MockRepository.GenerateMock<ISomeStub>();
someStub.Stub(x => x.SomeMethod(1)).Return(ReturnVal);
}

in your subclass:

  [TestInitialize]
    public override Init()
    {
    ReturnVal = 200;
    base.Init();
    }
Jonny Cundall
A: 

Yes, this is the designed behaviour.

The workaround I use most of the time is to create a helper method that will set up the stub for you, i.e.:

private X MockX()
{
  return MockX(100);  
}

private X MockX(int returnValue)
{
  var x = MockRepository.GenerateStub<X>();
  someStub.Stub(x => x.SomeMethod(1)).Return(returnValue);
  return x;
}

and then in your test instead of using a mock created in SetUp, you call the appropriate function. The added benefit is that it is clear that your test is using some special values of the return values.

Grzenio
Sorry, I didn't understand your example. How does it help to solve the problem?
Idsa
A: 

You can use mocks instead of stubs to record a scenario like that:

[Test]
public void Mytest()
{
   var mocks = new MockRepository();
   var someMock = mocks.DynamicMock<IFoo>();
   someMock.SomeMethod(1);
   LastCall.Return(100);
   someMock.SomeMethod(1);
   LastCall.Return(200);
   mock.Replay(); // stop recording, go to replay mode

   // actual test, normally you would test something which uses the mock here
   int firstResult = someMock.SomeMethod(1);
   int secondResult = someMock.SomeMethod(2);

   // verify the expectations that were set up earlier 
   // (will fail if SomeMethod is not called as in the recorded scenario)
   someMock.VerifyAll();
}

Mocks in Rhino Mocks are more complicated to set up than stubs. They also mix the definition of behavior with the creation of assertions (the record phase does both), and they rely on the ordering of method calls. This makes for brittle tests; stick to stubs unless you really need mocks.

Wim Coenen