Let's pretend that we want some dummy data available for use in our specs. We can ensure that each spec gets its own data set by creating a behavior.
First, let's register our behavior. This time, we want it to only apply to specs that implement a specific interface: INeedDummyData.
βxWhenTesting<INeedDummyData>().EnrichWith<DummyDataProviderBehavior>();
Now let's define our INeedDummyData interface:
xxxxxxxxxx
1public interface INeedDummyData : ISpecs
{
IEnumerable<Foo> Foos { get; set; }
}
The interface defines a single writable property: Foos. Our behavior will create some Foo objects and assign them there for the spec to use.
Here's our behavior:
xxxxxxxxxx
114public class DummyDataProviderBehavior : Behavior<INeedDummyData>
{
public override void Given(INeedDummyData instance)
{
instance.Foos = new[]
{
new Foo {Id = Guid.NewGuid(), Name = "Foo 1"},
new Foo {Id = Guid.NewGuid(), Name = "Foo 2"},
new Foo {Id = Guid.NewGuid(), Name = "Foo 3"},
new Foo {Id = Guid.NewGuid(), Name = "Foo 4"},
new Foo {Id = Guid.NewGuid(), Name = "Foo 5"},
};
}
}
Now our specs have access to a collection of Foo's that they can use, without having to do anything special:
xxxxxxxxxx
111public class when_a_spec_has_the_right_marker_interface
: SpecsFor<Foo>, INeedDummyData
{
public IEnumerable<Foo> Foos { get; set; }
β
[Test]
public void then_it_injects_some_foos()
{
Foos.ShouldNotBeEmpty();
}
}
You can also use a behavior to modify the [auto-mocking](πο»Ώ) container:
xxxxxxxxxx
122//In your spec config..
WhenTesting<INeedMockHelloService>().EnrichWith<MockHelloServiceBehavior>();
WhenTesting<INeedRealHelloService>().EnrichWith<RealHelloServiceBehavior>();
β
//These would go somewhere else
public class MockHelloServiceBehavior : Behavior<INeedMockHelloService>
{
public override void SpecInit(INeedMockHelloService instance)
{
instance.GetMockFor<IHelloService>()
.Setup(x => x.SayHello())
.Returns("Hello from Moq instance!");
}
}
β
public class RealHelloServiceBehavior : Behavior<INeedRealHelloService>
{
public override void SpecInit(INeedRealHelloService instance)
{
instance.MockContainer.Inject<IHelloService>(new HelloService());
}
}
Specs can then request either the real service or the pre-configured mock object by implementing the corresponding marker interface.
xxxxxxxxxx
122public class HelloSpecs
{
public class when_using_the_real_hello_service
: SpecsFor<HelloConsumer>, INeedRealHelloService
{
[Test]
public void then_it_returns_the_real_string()
{
SUT.GetHelloMessage().ShouldEqual("Hello from HelloService!");
}
}
β
public class when_using_the_mock_hello_service
: SpecsFor<HelloConsumer>, INeedMockHelloService
{
[Test]
public void then_it_returns_the_mock_string()
{
SUT.GetHelloMessage().ShouldEqual("Hello from Moq instance!");
}
}
}
Behaviors can do more than just define state before a spec executes. [They can also clean things up after a spec executes](πο»Ώ).