cobra icon indicating copy to clipboard operation
cobra copied to clipboard

No way to clear initializers for testing

Open electrofelix opened this issue 4 years ago • 5 comments

If you use a function to create a new instance of a command to allow testing with different arg inputs without risk of state being preserved between tests, can run into an issue if also making use of cobra.OnInitialize().

Currently using cobra.OnInitialize() to work around spf13/viper#397 as being able to mark some flags as required if a particular flag is not set before the preRun fires to check if all required flags are provided.

Similar in many ways to the code at https://github.com/spf13/viper/pull/852#issuecomment-592243347

However during testing I noticed that in order to be able to provide the cmd instance for the function passed to cobra.OnInitialize() it's necessary to have it part of the same function creating the command, which in turn means that each test that calls this is appending another function to the initializers at https://github.com/spf13/cobra/blob/master/cobra.go#L82-L84

This appears to cause a certain amount of interesting behaviour because each initializer will contain a reference to the command as created when that initializer was being appended, meaning the code will execute an initiailizer for however many instances of the command were created for testing.

When looking to trigger a panic by removing required flags in one of the tests via cmd.ResetFlags(), this prevents any subsequent test from running because the initializers contain an instance of the code from https://github.com/spf13/viper/pull/852#issuecomment-592243347 that will attempt to always execute on an instance of the command missing flags.

To workaround, can move this test to be the last one, however it seems like it would be useful to have ResetInitializers() function similar to the ResetFlags() to facilitate testing of code that is making use of OnInitialize().

My current approach is flip flopping between

  • move test to end
  • restore removed flags to the command via a t.Cleanup and custom function to reattach all previously defined flags
  • modify the function passed to cobra.OnInitialize() to limit it's execution to be once only and skipped subsequently allowing only the most recent addition to have an effect

electrofelix avatar Jul 28 '20 17:07 electrofelix

This issue is being marked as stale due to a long period of inactivity

github-actions[bot] avatar Sep 27 '20 00:09 github-actions[bot]

Unless I've missed an update this is still a problem

electrofelix avatar Sep 27 '20 16:09 electrofelix

FWIW, I have the same problem - didn't find it when I tested here -https://github.com/spf13/cobra/issues/1367

aronchick avatar Mar 27 '21 23:03 aronchick

My approach was always to separate out the logic from the CLI handling and to try and not avoid on the init type logic because of the issues you've described here.

When I couldn't get away from it, I moved whatever logic was in init style methods and extract them so that my tests could call those manually. Then you end up without any repeated code except maybe an extra reference to this init logic.

The init logic can contain any generic logic though as opposed to resetting flags; its not always as trivial (or desirable) to re-run initializers and we'd be unable to 'undo' their effect in any general sense.

Could you clarify exactly what it is that you're hoping for as a result of this? In @aronchick 's issue they mention wanting to reset all the flags; is that it: to traverse the commands/parents/children and reset all the flags?

johnSchnake avatar Feb 16 '22 20:02 johnSchnake

Same problem here. And it is sad to see unsolved issues being closed automatically by bots. 😞

silvioprog avatar Sep 02 '22 00:09 silvioprog