lundi 17 mai 2021

Is self injection a good practice? Same class injection programming pattern in PHP

Is injection of the same class a good practice?

I am using self-injection for years to isolate methods during PHPunit testing:

class Meter extends Model
{
    use SomeTrait;

    protected self $self;

    public function __construct(array $attributes = [])
    {
        parent::__construct($attributes);
        $this->self = $this;
    }

    public function setSelfDI(self $self): self
    {
        $this->self = $self;
        return $this;
    }

    public function calculate(): int
    {
        return $this->self->getDiametr() * 3.1415926;
    }
    
    public function getDiametr(): int
    {
        return parent::getRadius() * 2;
    }
    
}

to test calculate() method I can't just call it since it calls method getDiametr() which depends on other trait or class. And I believe it is bad practice to test mocked class.

So I inject mocked class in my class and so isolate method during testing:

public function testCalculate(): void
{
    /** @var Meter|MockObject $mock */
    $mock = $this->createMock(Meter::class);
    $mock->expects($this->once())
        ->method('getDiametr')
        ->willReturn(100);
        
    $meter = new Meter();
    $meter->setSelfDI($mock);
    static::assertEquals(314.15926, $meter->calculate());
}

It works perfectly for me.

But recently I got a code review that it is not a valid pattern to introduce synthetic functionality setSelfDI() on top of functional code just to be able to test it.

Now I have a normal DI pattern that I love to use vs setSelfDI() setter that is never used but for tests.

How to decide it is good or bad practice?

Aucun commentaire:

Enregistrer un commentaire