thephpleague / factory-muffin

Enables the rapid creation of objects for testing
https://factory-muffin.thephpleague.com/
MIT License
532 stars 72 forks source link

Allow write to private properties and/or create instance without constructor calling #459

Open JanMikes opened 5 years ago

JanMikes commented 5 years ago

Hello, i have private constructor for my entities, which was a problem. As well i have NO setters (i am huge fan of DDD).

I was able to create instances of entities without calling constructor and setting private properties without any setters like this:

/** @var FactoryMuffin $fm */
$fm->define(User::class)->setMaker(function() {
    $user = (new \ReflectionClass(User::class))->newInstanceWithoutConstructor();

    $property = new \ReflectionProperty(User::class, 'emailAddress');
    $property->setAccessible(true);
    $property->setValue($user, EmailAddress::fromString('john@doe.com'));

    $property = new \ReflectionProperty(User::class, 'passwordHash');
    $property->setAccessible(true);
    $property->setValue($user, ClearTextPassword::fromString('123')->makeHash());

    return $user;
});

I believe that the FactoryMuffin::generate() method could be rewritten like this (added as another possible fallback), rewrite this:

if (method_exists($model, $setter) && is_callable([$model, $setter])) {
                $model->$setter($value);
            } else {
                $model->$key = $value;
            }

To set value via property reflection.

JanMikes commented 5 years ago

Possibly related to #447