IDisposable Handling / Hierarchy of Fixtures Objects management

Oct 18, 2010 at 3:25 PM
Edited Oct 19, 2010 at 12:05 PM

I'm wondering whether you've ever thought of having  the Fixture class:

a) implement IDisposable

b) call Dispose() on every Fixture.Inject'd object when Dispose is called

Contextual babble:

I use a fork of xUnit's SubSpec http://bitbucket.org/johannesrudolph/subspec/overview

As part of doing the Context, sometimes one needs to IDisposable.Dispose() some of the fixtures after each run.

In xUnit, normally you can use a using block to manage that cleanly - so if you have 3 Fixtures (in XUTP parlance) in your test and two are Disposable, you might:

using(new A())

{

new B()

using (new C(a,b))

       var sut = CreateSut();

       sut.DoStuff();

Assert(sut.MyBAndCUpdatedMyCCorrectly();

}

In SubSpec, the context setup stuff takes place in a lambda so there's no easy way to have the Context/Arrange and Assert blocks share state. In Johannes' fork, you can register an IDisposable in your context to be tidied at the end of the test run. (And one has a CompositeContext which aggregates them). This means your idiomatic code becomes:

var sut = default(Sut);

"Given"

  .ContextFixture( () =>

  {

    var a = new A();

    new B()

    var c = new C(a,b);

    sut = CreateSut();

    return new AggregateContext { a,c};  

  });

"When"

  .Do( ()=>

    sut.DoStuff());

"Thus"

  .Observation(()=>

Assert(sut.MyBAndCUpdatedMyCCorrectly();

}

If Fixture worked differently, I could stash my fixtures in there via Inject() :-

var fixture = new Fixture();

var sut = default(Sut);

"Given"

  .ContextFixture( () =>

  {

    fixture.Inject( new A());

    new B()

    fixture.Inject( new C(a,b));

    sut = CreateSut();

    return _fixture;

  });

"When"

  .Do( ()=>

    sut.DoStuff());

"Thus"

  .Observation(()=>

Assert(sut.MyBAndCUpdatedMyCCorrectly();

}

Of course, in many cases, this might make end up making the test harder to follow.

I'm mainly wondering whether you've encountered such a set of situations that might also benefit from adding this capability to the Fixture class.

Failing that, is there a way to walk/Visit the list of Inject() registrations of a Fixture so I could do it myself (i.e., enable me to implement a DisposingFixture Decorator)?

I'm also _very_ open to suggestions that I'm Doing It Wrong - just looking for a quick sanity check; this is an idea more than a pattern that's been mined from 30 instances of a problem/solution pair

Coordinator
Oct 19, 2010 at 8:26 PM

Thanks for asking. Such a feature is not currently available, although it wouldn't be too hard implementing it as a custom Behavior (ISpecimenBuilderTransformation).

There's already an issue that tracks this feature, so if you need it, please go and vote for it. I could implement it in a couple of evenings, but had so far put it on the back-burner, as I didn't have the need for it myself :)

You are also welcome to attempt to contribute it yourself if you would like (but if you do, remember the unit tests) :)

Please let me know if you have further questions.

Coordinator
Oct 21, 2010 at 8:06 PM

I've just implemented this feature (in change set 05aeebffe7c1). See Ploeh.AutoFixtureUnitTest.Kernel.Scenario.DisposeCustomizationDisposesSpecimen() for an example.

Oct 22, 2010 at 10:03 AM

Wow, thanks! Sorry for going dark - from the Scenario it looks just right.

Mar 15, 2011 at 1:35 PM

OK, so I have:

class SutContext<T> : IDisposable
{
    readonly Fixture _fixture;
    readonly DisposableTrackingCustomization _tracking;
    readonly T _sut;

    public static SutContext<T> Create( out T sut )
    {
        var result = new SutContext<T>();
        sut = result._sut;
        return result;
    }

    SutContext()
    {
        _fixture = new Fixture();
        _tracking = new DisposableTrackingCustomization();
        _sut = _fixture.Freeze( (T)Activator.CreateInstance( typeof( T ), _fixture ) );
        _fixture.Customize( _tracking );
    }

    void IDisposable.Dispose()
    {
        _tracking.Dispose();
    }
}

Now in my test, I can do:

    [Specification]
    public static void TrackingSubSpecSample()
    {
        var sut = default( Sut );
        "Given a Sut"
            .ContextFixture( () =>
                SutContext<Sut>.Create( out sut ) );

        "that we exercise"
            .Do( () =>
                sut.Exercise() );

        "Looks exercised"
            .Observation( () =>
                Assert.True( sut.WasExercised ) );
    }

And I get
a) disposal of child fixtures
b) the ability to create trees of children and dependencies of the sut as desired

public class SutExample
{
    public class ChildFixture : IDisposable
    {
        bool _wasExercised;

        public void Exercise()
        {
            _wasExercised = true;
        }

        public bool WasExercised
        {
            get { return _wasExercised; }
        }

        void IDisposable.Dispose()
        {
            Console.WriteLine( "I got tidied up neatly!" );
        }
    }

    public class Sut
    {
        readonly ChildFixture _childFixture;

        public Sut( Fixture fixture )
        {
            _childFixture = fixture.Freeze<ChildFixture>();
        }

        public void Exercise()
        {
            _childFixture.Exercise();
        }

        public bool WasExercised
        {
            get { return _childFixture.WasExercised; }
        }
    }
}
Now, the question... is there a way to to stray into DI container land and generalize:
        _sut = _fixture.Freeze( (T)Activator.CreateInstance( typeof( T ), _fixture ) );
so that it works more like a DI Container's Get<T>() operation in that it would support:
a) resolving Fixture in ctor args of Sut -- example ugly thing I want/have to do is track objects created in factories that are instantiated by AutoFixture:-
 var childFactory = fixture.Freeze<ChildFactory>();
 _buildChild = fixture.Build<IChild>().FromFactory( childFactory.CreateChild ).CreateAnonymous;
b) resolving arbitrary dependencies in ctor args of Sut
c) perhaps stuff [Frozen] a la the xunit support as a modifier (I know I can customize to do it, just wondering if there's a way to leverage the existing stuff)

As before, I'm extremely open to criticism or having some or all of this called out as an antipattern...

The main thing I'm trying to do is to have my Sut's dispose also Dispose child fixtures - in general one doesnt often need to enable tracking on objects created from child fixtures that are factories
Coordinator
Mar 15, 2011 at 2:26 PM

I'm going to be slightly Jeremy Miller-esque here and ask you why you need child Fixtures? In the almost two years I've used AutoFixture so far, I've never felt the need for child Fixtures, and I can't understand from your example just why you'd want a thing like that.

Since I haven't really tried it out I don't know whether this would work, but have you tried to Inject the Fixture instance into itself and then just resolve specimens using the normal CreateAnonymous method? It might give you an exception because of infinite recursion, but I actually don't think so...

Basically I'm not a fan of any API design that hinges on static data, but it looks to me that this is a requirement of the BDD framework you are using - is that correct?

The [Frozen] attribute simply applies a Ploeh.AutoFixture.FreezingCustomization.

I'm pretty sure I addressed less than half of your questions, so please write again. There's just a lot of stuff here, and I feel that I'm missing several pieces of the puzzle to be able to give you a proper answer.

Mar 15, 2011 at 5:06 PM

Thanks for the quick response - much appreciated.

The Inject(_fixture) trick works nicely.

Now, onto the rest.

Background, not important, will provide salient bits here (having said that, the code is clean, interesting and less that 1000 lines and Hanselman says we should read it :D)... SubSpec is an xUnit extension that started as a desire by Phil Haack and was implemented by Brad Wilson as an xunit sample. A colleague, Johannes Rudolph has forked the sample to add some more capabilities, see https://bitbucket.org/johannesrudolph/subspec/wiki/Home

There is a SpecificationBaseStyle variant of SubSpec which works like idiomatic xunit - porting/generalising AutoFixture.xunit to it would be easy.

Regarding your contention that it relies on anything static, not really. The Specification method when run stashes a set of lambdas for Given When and multiple Then portions. SubSpec then, a la [Theory] runs a separate Given and When pair for each Then and the test names are based on the strings logged with the lambdas.

So, how does this affect what one'd need to match AutoFixture.xUnit and/or xUnit's normal IUseFixture support?

Firstly, we lose using blocks within the body of the Specification - you're generating 3 lambdas which can share state via the closure but can't e.g. do try/finally or using between blocks

Secondly, if you have multiple things to Dispose, you can normally IUseFixture them separately (or use an aggregate item that manages a set)

So, if your Sut needs disposal, the normal ways - using blocks or IUseFixture are not available

The other case is where one needs to Do something in the When bit which requires cleanup *after* the Then/Assert bit. This doesnt happen often, and normally in a Fact you'd either just use a using (which would include the When bit) or maintain a RX System.CompositeDisposable or a List<IDisposable> and have that torn down at the end (but it needs to be reliable). The other normal means of managing all this is to stash stuff in the Test Class instance and have it's Dispose do the cleanup.

The other thing that the lambdas make difficult is to share state between the G/W/T blocks - you need to declare them outside the lambdas, default initialize them to avoid the uninitialized variable warnings and then they get captured in a closure

So, why would you want to even use a framework like that?

1) it (by coincidence, but the effect is desirable) optimises for the SUT case - there's a friction to sharing state between the G/W/T phases

2) it lets you put English language spec level descriptions of intent without_underscores_that_are_ugly or CrazyPascalCasing without having to take the hit of something heavier like specflow and its extra assemblies, generated code etc. (esp if you dont have a magic BA that's going to write or read the Gherkin with you)

3) it's just xunit.net with <1000 lines added

With the above in mind, what falls out is that:

- we want a single SUT

- if the SUT needs access to 5 fixtures, it should be able to get them easily

- the SUT *and the fixtures* may need disposal 

 

The final piece is that right now, AutoFixute.xunit allows me to do

 

    void Test(Sut sut, [Frozen] Fixture1 fixture1, [Frozen] Fixture2 fixture2)
    {
    }

But I cant use it -- so I'm thinking that having the Sut be a SpecContext which

 

    class SutContext
    {
        Fixture1 _fixture1;

        public SutContext(Sut sut, [Frozen] Fixture1 fixture1, [Frozen] Fixture2 fixture2)
        {
		_fixture1 = fixture1;
        }

        void SomethingInTheWhen()
        {
            _fixture1.Something();
        }
    }

... But there's no way to say

using(var fixture = new DisposingFixture()) // Fixture with a disposer hooked in
{
   var context = fixture.CreateAnonymous<SutContext>()
   context.SomethingInTheWhen()
}
And have the ctor args be .Freeze<T> rather than CreateAnonymous<T> on a case by case basis. 
I could easily use the AutoFixture.xunit stuff as inspiration to achieve it, but am wondering whether there's something more built in. If I looked at the tests I'm sure I'll figure out how to write such a 5 line customization - was just looking to be lazy!
In closing, the niceness of AutoFixture.xunit and all this noise is all but pushing me back to using raw XUnit or considering the SpecificationBaseStyle SubSpec. Or StoryQ...
Thanks for the food for thought and hope you can provide some insights ideas without it stealing too much of your time -- it's nice to get better test reviews for free than are offered over wtwitter by paying something small like $100 per half hour :P
Mar 18, 2011 at 10:59 AM

Sorry about the long post(s) and the teddybearing - they help me to figure out my thoughts (though msot people have the sense not to hit save once they've done that!)

So in other words, I'm talking about usurping Fixture as a test context, not just an Object Mother.

I've realised I can just .Inject a RX. System.Disposables.CompositeDisposable (or reimplementaiton thereof) .Build't by AutoFixture as a way of being able to stash things in the case where I do have temp object that I need to create in the Act stage but have them live until the Assert stage

IOW I have a more appropriate way than forcing all factory methods that create disposables to go through:

 _buildChild = fixture.Build<IChild>().FromFactory( childFactory.CreateChild ).CreateAnonymous;

of managing how stuff can get disposed that isnt twisting what AF is for as needed

My remaining "thing that would be nice for AF to do" is to have a generalised mechanism where you can put a [Frozen] on

a) Fixture ctor parameters

b) .Get<> parameters

just like the xunit AutoData support extension does as a way to be able to define e.g. be able to spin up 5 fixtures with a single declaration statement as opposed to 5 CreateAnonymous vs Freeze statements that need to be unpicked

Does that (use param list with [Frozen] on some items as a way to be able to establish a set of objects needed for a test context as that's a relatively common _and desirable_ thing that's not an antipattern) make any sense for me to attempt to express as a clear Issue?

Coordinator
Mar 20, 2011 at 3:20 PM

I'm sorry, but I'm still not really getting what it is that you are trying to do... It seems overly complex, but it's probably because I don't understand what it is you are trying to accomplish...

What do you mean by putting [Frozen] on "Fixture ctor parameters" and ".Get<> parameters"? What would the API look like?

As a general observation, if SubSpec makes it difficult to dispose of objects created during the test, I would think that's a general issue that goes much further than AutoFixture. How does the framework deal with the issue if AutoFixture was not involved?

I'd love to help, but I feel we're a bit stuck here. How do we move on from here?

Mar 31, 2011 at 8:53 AM
Edited Mar 31, 2011 at 8:56 AM

Sorry about going dark for a record length of time, even for me...

Good probing on SubSpec - while its only a throwaway prototype and not entirely by design, the fact that the xunit IUseFixture stuff doesnt get called when running SubSpec tests is actually interesting in that its far less tempting to go stuffing bits of your Act into the Arrange (ctors, base ctors). It forces you to make all context/fixture establishment be readable / concise / DRY rather than a rats nest as e.g. NUnit/MSTest tends to not push people away from. I guess there's nothing preventing me from keeping a registry (perhaps as a RX System.CoreEx::CompositeDisposable ) and getting SubSpec to dispose the Test Class and do it that way.

Now, onto the thing that I think AF could do which it doesnt already do.

At present, you enable:

[Fact]
public X( FixtureA a, [Frozen] FixtureB b)
{
   a.Process(b);
}

While I havent looked at the exact impl, and there may be a nice way (likely there is, given my experiences of wanting to do any of this sort of thing with xunit) to do the equivalent of what you've done for xunit in SubSpec with minor work, what I'm looking for can be expressed by saying "can you make it do this:-

[Fact]
public X( )
{
    Fixture f = new Fixture();
    LambdaWrapper( () =>
        f.WithAnonymouses(
            (FixtureA a, [Frozen] FixtureB b) =>
               a.Process(b)));

}

I know that the AutoData mechanism prob hooks into the xunit Data Driven Tests support to achieve its aims so its hardly a straight port / extract of code, but if you could reflect over the signature of the lambda passed to WithAnonymouses (rather than going into expression trees), you'd save me from having to do:

  LambdaWrapper( ()=>
        f.WithAnonymouses(
            () => {
               a = f.CreateAnonymous<FixtureA>();
               b = f.Freeze<FixtureB>();
               a.Process(b);
           } ));

The reason I refer to all of this as Get<> is that you have an API that does similar stuff but AFAICT you cant lob a [Frozen] on parameters? If something like this was possible, it would enable SubSpec to support something a la:

[AutoFixtureSpecification]
public AsProcessingBsShouldFly()
{
    "When an A processes a B".Do(
       (FixtureA a, [Frozen] FixtureB b) =>
         a.Process(b));
}

Man do I love SO's markdown compared to sticking code in this monster!

(The reason one cant send it in as xunit Data is that one Test Method invocation can potentially lead to multiple runs - i.e. for a given element of a [Theory], there may need to be separate invocations of the Arrange/Act for multiple Assert sections)

Hope this explains stuff slightly better than the prev post

Coordinator
Mar 31, 2011 at 6:58 PM

I don't know if you've noticed two extension methods for IFixture (actually for ISpecimenBuilderComposer) called Do and Get? They already have the signature that you request, although not the capability.

So, what you are asking for is to enable to Do and Get methods to understand Ploeh.AutoFixture.Xunit.CustomizeAttribute? Perhaps by moving those attributes from the xUnit.net extension to AutoFixture proper. If so, you'd be able do something like this:

fixture.Do((A a, [Frozen]B b) => a.DoStuffTo(b));

Is this what you are asking for?

I can't really decide whether that's something I'd want to do, though. My main concern is that, if done to the Get method, it violates CQS and thus possibly also the POLA. Another minor detail is that it would also require a change of signature of the Do and Get methods to work on IFixture instead of ISpecimenBuilderComposer, which is a breaking change...

However, it wouldn't be hard to implement. You'd just need to combine the implementation of the Do and Get methods with the implementation from Ploeh.AutoFixture.Xunit.GetData(MethodInfo, Type[]).

Is this in any way helpful?

Apr 1, 2011 at 8:42 AM
Edited Apr 1, 2011 at 8:43 AM

Yes, I was referring to the same Get of which you speak.

I wasnt aware that Do had similar overloads (probably as I'm not paying attention - I have no doubt its well documented). So that makes my WithAnonymouses up there already implemented.

Was pondering whether you need to do especially funky stuff to get at the attributes on the lambda params (thinking ugly reflection against internals of MulticastDelegate?) ?

Good point on the cons. Its all fine when you're only using it to establish context in a clearly defined manner analagous to the protocol and prior art of xUnit.net test method params, but as a generalised thing to go in the core, it probably makes less sense. The other thing is that SubSpec forces you to put all related stuff in one top level test method - i.e., in idiomatic tests one wouldnt pass the Fixture out of the method so the POLA would be less of an issue.

While my example uses the SubSpec Do (Act phase), I was really talking about the Context (Arrange phase). In general, not much should be going on in the Do phase wrt requiring fixtures etc - they should all be established in the Context and then used in the Do. Having said that, there's no reason why the same thing shouldnt be offered (even though it'd see much less usage that the same support on the Context method would). Having said that, if Frozen was available, you could shorten:

[AutoFixtureSpecification]
public AsProcessingBsShouldFly()
{
    var tempB = default(FixtureB);
    "Given an B has been configured"
        .Context( ([Frozen] FixtureB b)=>
            tempB);

    "When an A processes it"
        .Do( (FixtureA a) =>
             a.Process(tempB));
}

to:

[AutoFixtureSpecification]
public AsProcessingBsShouldFly()
{
    "Given an B has been configured"
       .Context( ([Frozen] FixtureB b)=>{});
    "When an A processes it"
        .Do( (FixtureA a, FixtureB b) =>
             a.Process(b));
}

The above also illustrates your CQS point too( the Context statement would have frozen the FixtureB but you dont see that fact on the sig of the Do)

BTW Can one stick attributes on lambda params? Answer: No! 

Cant think of a way to manage it without maybe having some generic wrapper around the parameter. Perhaps that route might also offer an approach that offers less astonishment? It'd def make the impl cleaner (assuming my point about the ugliness of getting the custom attributes off the lambda params if it was even possible to put them there)

--R

Coordinator
Apr 3, 2011 at 7:13 PM

So you're saying that the following is not possible because it's impossible to attach attributes on lambda parameters:

fixture.Do(([Frozen]Foo f) => { });
(I didn't look it up, but I read your post to indicate that this doesn't compile.)

Perhaps you could introduce a signal type like Frozen<T> and an ISpecimenBuilder that would intercept all requests for Frozen<T> to freeze an instance of T and wrap it in an instance of Frozen<T>. That might enable you to write:

fixture.Do((Frozen<Foo> f) => { });

You could even have an implicit conversion from Frozen<T> to T if that would help - otherwise you could access the T via a Value property. The interface would look much like Lazy<T>.

Another alternative would be to introduce a convention so that if the parameter name starts with frozen it would be frozen:

fixture.Do((Foo frozenFoo) => { });
Would any of that help?