nextras / orm

Orm with clean object design, smart relationship loading and powerful collections.
https://nextras.org/orm
MIT License
310 stars 59 forks source link

Add Entity::setMetadata() method #181

Open f3l1x opened 8 years ago

f3l1x commented 8 years ago

This is probably not an issue. I would like to test my components. They are very simple just for save entity let say. I've created mock of my facade and should receive a new fresh entity in save method, so this test is without access to database, no sql queries.

But I've got this message: Nextras\Orm\InvalidStateException: MetadataStorage::get() called too early. You have to instantiate your model first..

Here is component`s code.

public function processForm(SupplierForm $form)
{
        $values = $form->getValues();
        $entity = new Foo();
        // ....
        $this->facade->save($entity);
}

Any idea how to change concept? I think my architecture isn't bad I've just wanted to know the correct solution. I can't use EntityCreater it's not a test it's real component.

Thank you.

JanTvrdik commented 8 years ago

The error means that you created instance of entity before creating instance of IModel. Create instance of IModel first.

f3l1x commented 8 years ago

@JanTvrdik I know, but it's little bit tricky if you want to just create entity and verify it was passed to your mock. Don't you think?

hrach commented 8 years ago

For now, you can mock IRepository & Metadata and call onAttach. But I will probably create a Metadata setter for better test usability.

f3l1x commented 8 years ago

Setter would be nice. I get it why it's in constructor, but we might think about better solution. Perhaps setter. :-)

f3l1x commented 7 years ago

Any updates here? It's really complicated to create simple unit tests..

dakorpar commented 5 years ago

Just having same issue, any news regarding this? I'm using phpunit and in this case now I've created method in my BaseTest:

 /**
 * @var array
 */
private $_data = [];

public function createEntityMock(string $classType): MockObject
{
    $entity = $this->getMockBuilder($classType)
        ->disableOriginalConstructor()
        ->getMock();

    $entity->method('__set')->willReturnCallback(function($name, $value) use ($classType) {
        $this->_data[$classType][$name] = $value;
    });

    $entity->method('__get')->willReturnCallback(function($name) use ($classType) {
        return $this->_data[$classType][$name];
    });

    return $entity;
}
hrach commented 5 years ago

As mentioned in https://github.com/nextras/orm/issues/181#issuecomment-299906224 you may set the Metadata by onAttach. Actually not sure adding setMetadata would be good. It would pollute interface and API for common usage.