Request: Add Clone Method to IFixture
See original GitHub issueIntroduction
I would like if IFixture
had a Clone
method or something similar to create a copy of the fixture.
At the moment I can create an extension method to do this:
public static IFixture Clone( this IFixture fixture)
{
var cloneFixture = new Fixture();
cloneFixture.Behaviors.Clear();
foreach ( var behavior in fixture.Behaviors)
{
cloneFixture.Behaviors.Add( behavior );
}
cloneFixture.Customizations.Clear();
foreach ( var customization in fixture.Customizations )
{
cloneFixture.Customizations.Add( customization );
}
cloneFixture.OmitAutoProperties = fixture.OmitAutoProperties;
cloneFixture.RepeatCount = fixture.RepeatCount;
cloneFixture.ResidueCollectors.Clear();
foreach ( var residueCollector in fixture.ResidueCollectors )
{
cloneFixture.ResidueCollectors.Add( residueCollector );
}
return cloneFixture;
}
But I feel such an ability to make a copy ought to be in the project itself.
Details
My scenario is I construct a couple instances of a class with a lot of parameters in a test. In addition I want to have a constructor parameter be a certain value for one instance and a different constructor value for a different instance. There are several ways I can do this; the way I have been doing it is:
fixture.Customizations.Add( new FilteringSpecimenBuilder(
new FixedBuilder( mediaId ),
new ParameterSpecification(
typeof( ObjectId ),
"mediaId" ) ) );
var mediaVM = fixture.Build<MediaViewModel>()
.With( mvm => mvm.ParentMixerId, mixerId )
.With( mvm => mvm.TrackId, trackId )
.Create();
_ = fixture.Customizations.Remove( fixture.Customizations.Last() );
//...
The reason for the removal of the customization is I tried without it thinking maybe the last customization added will have a higher precedence and be used; but it wasn’t the case.
If I try to simplify this with some sort of extension method like so:
public static IFixture AddCustomization<T>( this IFixture fixture, T value, string name )
{
fixture.Customizations.Add( new FilteringSpecimenBuilder(
new FixedBuilder( value ),
new ParameterSpecification(
typeof( T ),
name ) ) );
return fixture;
}
It might work in some places but won’t in others because after the object is built the fixture contains a customization I no longer desire and I need to remove.
I would prefer not to have a line to remove the added customization(s). So if instead my extension method made a copy of my fixture to which I add modifications to the copy then my creations works as expected and the original fixture is untouched.
Also would work is the ability to add a customization that is automatically removed after the object is created.
Hope this all makes sense.
Thanks for considering my issue 😃
Issue Analytics
- State:
- Created 3 years ago
- Comments:9 (5 by maintainers)
Top GitHub Comments
@ajorians I was about to close the issue due to inactivity but I could not walk by that gigantic constructor. I got to ask, have you considered changing your design?
By looking at your constructor I can see several issues and potential solutions to your problem.
First of all you are mixing the concepts of newable and injectable entities. The most straightforward solution is to move your injectable dependencies (aka Service Interfaces) to properties and inject them using property injection. This will solve your immediate problem of having to copy the
Fixture
and will make the constructor more manageable.Second is addressing the over-injection code smell. This means moving away the most commonly used together services into separate abstractions. This should help your design respect the SRP and by extention it should reduce the huge amount of setup you have to do at the moment, in your tests.
Since the class is called
ViewModel
I assume you have a MVVM application. It is likely that you could further decouple your application by introducing a messaging model. Perhaps an event aggregator. Most MVVM frameworks have them built in so you don’t have to do a lot of setup work, to benefit from them.Let me know if this helps.
Hi @aivascu ,
OK. Well thank you for considering.
I’ll take a look.
Thanks again! 😃