question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Request: Add Clone Method to IFixture

See original GitHub issue

Introduction

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:closed
  • Created 3 years ago
  • Comments:9 (5 by maintainers)

github_iconTop GitHub Comments

2reactions
aivascucommented, Dec 8, 2020

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

1reaction
ajorianscommented, Dec 9, 2020

Hi @aivascu ,

@ajorians my opinion is that we should not add a .Clone() method to the Fixture class.

OK. Well thank you for considering.

What you can do is implement a relay that ignores the requests after a certain count of successful resolutions

I’ll take a look.

Thanks again! 😃

Read more comments on GitHub >

github_iconTop Results From Across the Web

Choose Clone Method Window - dot2 User Manual
If you try to clone a fixture, the console ask to choose the clone method. Figure 1: Choose clone method window. There are...
Read more >
How to pass a fixture as param to another fixture
It seems like you can just use request.getfixturevalue to get the return value of the fixture instead of the function object.
Read more >
How to use fixtures — pytest documentation
“Autouse” fixtures are a convenient way to make all tests automatically request them. This can cut out a lot of redundant requests, and...
Read more >
Request: clone() method - Web APIs | MDN
The clone() method of the Request interface creates a copy of the current Request object.
Read more >
Failing to clone or swap fixtures between old and new ...
You can not really clone between types, there is an exchange button to fully replace the fixtures instead. However a fixture like Beyond...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found