I have the following code. I have a somewhat legitimate reason for stubbing that property twice (See explanation below). It looks like it's only letting me stub it once.
private IStatus _status;
[SetUp()]
public void Setup() {
this._status = MockRepository.GenerateStub<IStatus>();
this._status.Stub(x => x.Connected()).Return(true);
// This next line would usually be in the Setup for a subclass
this._status.Stub(x => x.Connected()).Return(false);
}
[Test()]
public void TestTheTestFramework() {
Assert.IsFalse(this._status.Connected()); // Fails...
}
public interface IStatus {
bool Connected { get; }
}
I tried downloading the most recent build (3.6 build 21), but still have the same issue. Any ideas on why I can't do this? I tried changing the Connected
property on IStatus
to be a function and the test still failed. I get the same behavior in VB.Net... Bug?
Explanation on the double-stubbing
I'm structuring my tests around inheritance. That way I can do common setup code just once, using injected mocked dependencies to simulate different conditions. I might provide a base/default stubbed value (e.g. yes, we're connected) which I'd want to override in the subclass that tests the behavior of the SUT when the connection is down. I usually end up with code like this.
[TestFixture()]
public class WhenPublishingAMessage {
// Common setup, inject SUT with mocked dependencies, etc...
[Test()]
public void ShouldAlwaysWriteLogMessage {
//Example of test that would pass for any sub-condition
}
[TestFixture()]
public class AndNoConnection : WhenPublishingAMessage {
// Do any additional setup, stub dependencies to simulate no connection
// Run tests for this condition
}
[TestFixture()]
public class AndHaveConnection : WhenPublishingAMessage {
// Do any additional setup and run tests for this condition
}
}
Edit
This post on the Rhino Mocks google group might be helpful. It looks like I might need to call this._status.BackToRecord();
to reset the state, so to speak... also, tacking on .Repeat.Any()
to the second stub statement seemed to help as well. I'll have to post more details later.
To sum everything up, there's a three different answers that are possible:
Specify a specific number of times to return on the first stub using .Repeat.Times(n)
, .Repeat.Once()
, .Repeat.Twice()
, etc. For example:
this._status.Stub(x => x.Connected()).Return(true).Repeat.Once();
this._status.Stub(x => x.Connected()).Return(false);
This method works pretty well if I know the number of times the stub will get called before I change it's behavior (e.g. it just gets called once in the constructor).
I don't like this method since I'd like to avoid the (at least to me) more cumbersome Expect/Verify Record/Replay type syntax. It was recommending to me in response to a post I made to the Rhino Mocks Google group with the same title as this question.
this._status.Stub(x => x.Connected).Return(true);
this._status.GetMockRepository().BackToRecordAll();
this._status.GetMockRepository().ReplayAll();
this._status.Stub(x => x.Connected).Return(false);
I found that using .Repeat.Any()
on the second stub overrode the first one work... I feel a bit bad adding some extra 'magic' code to make it work, but in the case where you don't know how often to tell the first stub to return, this option will work.
this._status.Stub(x => x.Connected()).Return(true);
this._status.Stub(x => x.Connected()).Return(false).Repeat.Any();
Note: you can't do .Repeat.Any()
more than once.