When making a quick test app to prove the use of WithFakerHub, I discovered a bug: The AutoFaker<T> class, when generating instances of T, initializes them with bogus data twice.
This is because in the Generate method, it sets up a CreateAction, and that CreateAction, whose job it is to produce an actual instance of T, does so by calling AutoGeneratorFactory.GetGenerator(context).Generate(context). The resulting T has its members initialized already -- but, a separate FinalizeAction is also registered, which overwrites whatever is already in the object, and the underlying Faker calls this via its PopulateInternal method before returning:
// Faker[T].cs line 458:
var instance = createRule(this.FakerHub);
PopulateInternal(instance, cleanRules);
return instance;
When the non-generic AutoFaker's Generate<TType> method is being used, it does not use Faker.Generate<TType> at all; instead, it goes directly to AutoBogus's AutoBinder and calls CreateInstance<TType> followed by PopulateInstance<TType>. This CreateInstance<TType> call does not fill the object with bogus data, so it only gets populated once.
The Binder.PopulateInstance<TType> is the same action that the FinalizeAction in AutoBogus<T> takes to populate the object, so I believe the correct thing for the CreateAction to be doing is Binder.CreateInstance<TType>. This makes the AutoFaker<T>.Generate flow parallel the actions that TypeGenerator takes when AutoFaker.Generate<TType> is used.
This PR adds a unit test that fails when the erroneous behaviour occurs, and makes this small change to the CreateAction used by AutoFaker<T> to fix the failing test.
When making a quick test app to prove the use of
WithFakerHub
, I discovered a bug: TheAutoFaker<T>
class, when generating instances ofT
, initializes them with bogus data twice.This is because in the
Generate
method, it sets up aCreateAction
, and thatCreateAction
, whose job it is to produce an actual instance ofT
, does so by callingAutoGeneratorFactory.GetGenerator(context).Generate(context)
. The resultingT
has its members initialized already -- but, a separateFinalizeAction
is also registered, which overwrites whatever is already in the object, and the underlyingFaker
calls this via itsPopulateInternal
method before returning:When the non-generic
AutoFaker
'sGenerate<TType>
method is being used, it does not useFaker.Generate<TType>
at all; instead, it goes directly toAutoBogus
'sAutoBinder
and callsCreateInstance<TType>
followed byPopulateInstance<TType>
. ThisCreateInstance<TType>
call does not fill the object with bogus data, so it only gets populated once.The
Binder.PopulateInstance<TType>
is the same action that theFinalizeAction
inAutoBogus<T>
takes to populate the object, so I believe the correct thing for theCreateAction
to be doing isBinder.CreateInstance<TType>
. This makes theAutoFaker<T>.Generate
flow parallel the actions thatTypeGenerator
takes whenAutoFaker.Generate<TType>
is used.This PR adds a unit test that fails when the erroneous behaviour occurs, and makes this small change to the
CreateAction
used byAutoFaker<T>
to fix the failing test.