Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mock container resolved class with parameters? - Laravel

I want to mock a class that is created using a static method

// this is how I instanciate the object
MyClass::from(AnotherClass $data);

// this is how the class looks like
class MyClass 
{
     protected function __construct(AnotherClass $data)
    {
        // do stuff
    }

     public static function from(AnotherClass $data): self
    {
        return new self($data);
    }
}

This is how I bind it to the container:

$this->app->bind(MyClass::class, function ($app, array $parameters) {
    return MyClass::from($parameters[0]);
});

This is how I use the class

$data = new AnotherClass()
app(MyClass::class, [$data])

I cannot store the $data globally to get rid of the parameter in my binding.

The problem is that when I try to mock or spy on MyClass it does not work.

$spy = spy(MyClass::class);
// ... do some stuff
$spy->shouldHaveReceived('reactPHPIdle');

If I dump app(MyClass::class) the mocked class is returned. But when I dump app(MyClass::class, [$data]) the original class is returned, not the mocked one.

How can I successfully mock my class? Is there a better way to do this (ex. refactor the class)?

like image 403
Cata Avatar asked Dec 11 '25 23:12

Cata


1 Answers

Mocking or spying registers an instance in the container. When providing an argument when resolving will make the container not take the instance, but rather use the bound function to create a new one.

To resolve this issue, you can overwrite the bound function in your test to return the spy. For example something like:

app()->bind(MyClass::class, function () use ($spy) {
    return $spy;
});
like image 102
closeneough Avatar answered Dec 14 '25 13:12

closeneough



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!