Source

SubSpec / test / SubSpec.Tests / ContextSetupTeardownBehavior.cs

Full commit
using System;
using SubSpec;
using Xunit;
using System.Collections.Generic;
using Moq;
using Xunit.Sdk;

public class ContextSetupTeardownBehavior
{
    public class ContextFixtureSpy
    {
        private bool called = false;
        public void FailWhenCallingTwice()
        {
            if (called)
                throw new InvalidOperationException( "Called twice!" );

            called = true;
        }
    }

    [Fact]
    public void SutThrowsWhenCalledTwice()
    {
        var sut = new ContextFixtureSpy();
        Assert.Throws<InvalidOperationException>( () =>
        {
            sut.FailWhenCallingTwice();
            sut.FailWhenCallingTwice();
        } );
    }

    [Specification]
    public void MultipleAssertionsShouldCauseActionToBeRepeated()
    {
        var sut = new ContextFixtureSpy();
        sut.FailWhenCallingTwice();

        "Given an externally managed context"
            .Context( () => { } );

        "when we execute an action on it that may be invoked only once"
            .Do( () =>
                Assert.Throws<InvalidOperationException>( () => sut.FailWhenCallingTwice() ) );

        "we expect our first assertion to pass"
            .Assert( () => 
                Assert.True( true ) );

        "we expect the action not to be repeated for the second assertion"
            .Assert( () =>  
                Assert.True( true ) );
    }

    [Specification]
    public void MultipleAssertionsShouldCauseContextInstantiationToBeRepeated()
    {
        var sut = new ContextFixtureSpy();
        sut.FailWhenCallingTwice();

        "Given a context that may not be established twice".Context(
            () => Assert.Throws<InvalidOperationException>( () => sut.FailWhenCallingTwice() ) );

        "".Do( () => { } );

        "we expect our first assertion to pass".Assert( () => { Assert.True( true ); } );
        "we expect the context instantiation not to be repeated for the second assertion".Assert( () => { Assert.True( true ); } );
    }

    [Specification]
    public void MultipleObservationsShouldNotCauseActionToBeRepeated()
    {
        var sut = new ContextFixtureSpy();

        "Given an externally managed context".Context( () => { } );
        "when we execute an action on it that may be invoked only once".Do( () => { sut.FailWhenCallingTwice(); } );

        "we expect our first assertion to pass".Observation( () => { Assert.True( true ); } );
        "we expect the action not to be repeated for the second assertion".Observation( () => { Assert.True( true ); } );
    }

    [Specification]
    public void MultipleObservationsShouldNotCauseContextInstantiationToBeRepeated()
    {
        var sut = new ContextFixtureSpy();

        "Given a context that may not be established twice".Context( () => { sut.FailWhenCallingTwice(); } );
        "".Do( () => { } );

        "we expect our first assertion to pass".Observation( () => { Assert.True( true ); } );
        "we expect the context instantiation not to be repeated for the second assertion".Observation( () => { Assert.True( true ); } );
    }

    [Fact]
    public void ErrorInDoForAssertionDisposesContext()
    {
        var m = new Mock<IDisposable>();

        SubSpec.Core.SpecificationContext.Context( "", () => { return m.Object; } );
        SubSpec.Core.SpecificationContext.Do( "", () => { throw new Exception( "" ); } );
        SubSpec.Core.SpecificationContext.Assert( "", () => { } );

        Mock<IMethodInfo> testMethod = new Mock<IMethodInfo>();
        testMethod.SetupGet( x => x.IsStatic ).Returns( true );

        SpecificationAttribute.FtoEnumerateTestCommands( testMethod.Object ).Consume();

        m.Verify( x => x.Dispose() );
    }

    [Fact]
    public void ErrorInDoForObservationDisposesContext()
    {
        var m = new Mock<IDisposable>();

        SubSpec.Core.SpecificationContext.Context( "", () => { return m.Object; } );
        SubSpec.Core.SpecificationContext.Do( "", () => { throw new Exception( "" ); } );
        SubSpec.Core.SpecificationContext.Observation( "", () => { } );

        Mock<IMethodInfo> testMethod = new Mock<IMethodInfo>();

        testMethod.SetupGet( x => x.IsStatic ).Returns( true ); SpecificationAttribute.FtoEnumerateTestCommands( testMethod.Object ).Consume();

        m.Verify( x => x.Dispose() );
    }
}

internal static partial class Mixin
{
    public static void Consume( this IEnumerable<ITestCommand> seq )
    {
        foreach (var item in seq)
        {   try
            {
                item.Execute(null);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }
    }
}