Using a behavior to define state

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.

WhenTesting<INeedDummyData>().EnrichWith<DummyDataProviderBehavior>();

Now let's define our INeedDummyData interface:

public 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:

public 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:

public 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:

//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.

public 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.