When using a mocking framework and MSPEC where do you set your stubs
I am relatively new to using MSpec and as I write more and more tests it becomes obvious to reduce duplication you often have to use a base class for your setup as per Rob Conery's article
I am ha开发者_JS百科ppy with using the AssertWasCalled method to verify my expectations, but where do you set up a stub's return value, I find it useful to set the context in the base class injecting my dependencies but that (I think) means that I need to set my stubs up in the Because delegate which just feels wrong.
Is there a better approach I am missing?
The initialization/setup of stubs belongs to the arrange phase. The arrange phase is used to get the system into a known state before you exercise it.
In MSpec, the arrange phase is performed in Establish
fields. For example:
public class When_the_temperature_threshold_is_reached
{
static ITemperatureSensor Sensor;
static Threshold Threshold;
Establish context = () =>
{
Sensor = MockRepository.GenerateStub<ITemperatureSensor>();
Sensor
.Stub(x => x.GetTemperature())
.Return(42);
Threshold = new Threshold(Sensor);
};
Because of = () => Reached = Threshold.IsReached(40);
It should_report_that_the_threshold_was_reached =
() => Reached.ShouldBeTrue();
}
When you write more tests using that kind of ITemperatureSensor
, you should extract a base class that does complicated or repeated setup.
public abstract class TemperatureSpecs
{
protected static ITemperatureSensor CreateSensorAlwaysReporting(int temperature)
{
var sensor = MockRepository.GenerateStub<ITemperatureSensor>();
sensor
.Stub(x => x.GetTemperature())
.Return(temperature);
return sensor;
}
}
public class When_the_temperature_threshold_is_reached : TemperatureSpecs
{
// Everything else cut for brevity.
Establish context = () =>
{
Sensor = CreateSensorAlwaysReporting(42);
Threshold = new Threshold(Sensor);
};
}
This gives you the advantage that you can influence the stub's return value from the context itself: You do this by keeping as much information as possible local to the context and provide a good name for the "setup" method in the base class.
There is no need to specifiy or expect anything stub-related in Because
. When Because
is run, your system should be in a state where it can be exercised without further preparation.
精彩评论