https://github.com/morrislaptop/popo-factory
Making it easy to mock your POPO's / Value Objects
https://github.com/morrislaptop/popo-factory
faker popo value
Last synced: about 1 year ago
JSON representation
Making it easy to mock your POPO's / Value Objects
- Host: GitHub
- URL: https://github.com/morrislaptop/popo-factory
- Owner: morrislaptop
- License: mit
- Created: 2021-01-23T19:02:45.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2023-11-01T20:11:57.000Z (over 2 years ago)
- Last Synced: 2025-03-26T03:51:16.763Z (about 1 year ago)
- Topics: faker, popo, value
- Language: PHP
- Homepage: https://github.com/morrislaptop/popo-factory
- Size: 68.4 KB
- Stars: 9
- Watchers: 2
- Forks: 4
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: .github/CONTRIBUTING.md
- License: LICENSE.md
- Security: .github/SECURITY.md
Awesome Lists containing this project
README
# Making it easy to mock your POPO's / Value Objects
[](https://packagist.org/packages/morrislaptop/popo-factory)
[](https://github.com/morrislaptop/popo-factory/actions?query=workflow%3ATests+branch%3Amaster)
[](https://packagist.org/packages/morrislaptop/popo-factory)
This package supports mocking POPOs or Value Objects, it inspects your class properties and populates them with random data generated by Faker. You can create class-based mock factories to have a fluent interface to mock POPOs for different states.
This is a fork of [Data Transfer Object Factory](https://github.com/anteris-dev/data-transfer-object-factory).
## Installation
You can install the package via composer:
```bash
composer require morrislaptop/popo-factory --dev
```
## Usage
```php
use Morrislaptop\PopoFactory\PopoFactory;
class PersonData
{
public function __construct(
public $firstName,
public string $lastName,
public string $email,
public string $homeAddress,
public ?string $companyName,
public string $workAddress,
public Carbon $dob,
public PersonData $spouse,
) {
}
}
PopoFactory::new(PersonData::class)->make();
```
Which creates an object that looks like this:
```json
{
"firstName": "Jada",
"lastName": "Bechtelar",
"email": "edmond.mcglynn@example.org",
"homeAddress": "640 Feest Landing\nBernierburgh, PA 99277",
"companyName": "Ratke Inc",
"workAddress": "75107 Konopelski Radial\nRutherfordport, AK 22994",
"dob": "2021-01-26T11:04:31.393991Z",
"spouse": {
"firstName": "Leola",
"lastName": "Koss",
"email": "friedrich41@example.org",
"homeAddress": "852 Fabian Mills\nNorth Ward, NM 54459",
"companyName": "Fahey and Sons",
"workAddress": "671 Creola Prairie Apt. 663\nNorth Gretchenview, OR 75622-4176"
}
}
```
The `new` method returns an instance of `Morrislaptop\PopoFactory\PopoFactory` which provides the following methods.
- `count()` - _Allows you to specify how many POPOs to be generated. They will be returned in an array._
- `make()` - _Called when you are ready to generate the POPO(s). Returns the generated object(s)._
- `random()` - _Generates a random number of POPOs_
- `sequence()` - _Alternates a specific state. (See below)_
- `state()` - _Manually sets properties based on the array of values passed._
Examples of these methods can be found below.
```php
// Creates two DTOs in an array
PopoFactory::new(PersonData::class)->count(2)->make();
// Sets the first name of every person to "Jim"
PopoFactory::new(PersonData::class)
->random()
->state([
'firstName' => 'Jim',
])
->make();
// Alternates the names of each person between "Jim" and "Susie"
PopoFactory::new(PersonData::class)
->random()
->sequence(
[ 'firstName' => 'Jim' ],
[ 'firstName' => 'Susie' ]
)
->make();
```
## Creating Class Based Factories
It's useful to define specific factories for particular objects, which can easily be done by extending the `PopoFactory` class.
My specifying a typehint for the `make()` method you will also get typehints in your IDE for your mocked object.
```php
/**
* @method PersonData make
*/
class PersonDataFactory extends PopoFactory
{
public static function factory(): static
{
return static::new(PersonData::class)->state([
'firstName' => 'Craig'
]);
}
public function gotNoJob() {
return $this->state([
'companyName' => null,
]);
}
public function worksAtHome() {
return $this->state(function ($attributes) {
return [
'workAddress' => $attributes['homeAddress']
];
});
}
}
```
Then using it in tests like so:
```php
$person = PersonDataFactory::factory()
->gotNoJob()
->worksAtHome()
->make();
```
## Extending
You can easily extend the factory to support other data types. You can do this through the static `registerProvider()` method on the `PropertyFactory` class. This method takes two arguments. The first should be the FQDN of the class you are providing (e.g. `Carbon\Carbon`) OR the built-in type (e.g. `string`). The second should be a callback that returns the generated value. This callback is passed two properties when called to assist in generating the value. The first is an instance of `Anteris\FakerMap\FakerMap` which can be used to help generate fake data. The second is an instance of `ReflectionProperty` which contains information about the property being generated.
For example, to support Carbon:
```php
use Morrislaptop\PopoFactory\PropertyFactory;
use Anteris\FakerMap\FakerMap;
PropertyFactory::registerProvider('Carbon\Carbon', fn(FakerMap $fakerMap) => Carbon::parse(
$fakerMap->closest('dateTime')->fake()
));
```
## Plug
Want an easy way to persist your POPOs in Laravel? Check out [laravel-popo-caster](https://github.com/morrislaptop/laravel-popo-caster)
## Testing
```bash
composer test
```
## Changelog
Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.
## Contributing
Please see [CONTRIBUTING](.github/CONTRIBUTING.md) for details.
## Security Vulnerabilities
Please review [our security policy](../../security/policy) on how to report security vulnerabilities.
## Credits
- [Craig Morris](https://github.com/morrislaptop)
- [All Contributors](../../contributors)
## License
The MIT License (MIT). Please see [License File](LICENSE.md) for more information.