Something like below?
$mockUser = Mockery::mock(User::class)
->shouldReceive('setName')->once()->andReturnSelf();
->getMock();
$mockUser::create('John');
Hello everyone. Let's say I have a class like this:
class User
{
public string $name;
public static function create(string $name): self
{
$user = new self();
return $user->setName($name);
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
}
I want to test that if I call User::create('John') then method setName has been called once. How can I achieve this? The fact is, that I should mock an object which will be instantiated during the create method.
I use PHPUnit as testing framework, but I accept answers that solve this via external libraries (e.g. Mockery)
EDIT
This is a toy problem and not the real application, which has been deliberately simplified to illustrate the problem.
Of course I know I can easily test the final result of the operation like in $this->assertEquals('John', User::create('John')), but this is not what I am asking.
I need to test if the setName method is being called on an instance of the User class.
P.S. This question is about Vanilla PHP + PHPUnit, it's not about Laravel.
For example, below is a very rudimentary implementation, but the test does pass without Laravel.
<?php
namespace Tests;
use Mockery;
class UserTest extends TestCase
{
public function testSetNameCalled(): void
{
$name = 'John';
$mockUser = Mockery::mock(User::class)
->shouldReceive('setName')->with($name)->once()->andReturnSelf()
->getMock();
App::bind(User::class, $mockUser);
User::create($name);
}
}
class User
{
public string $name;
public static function create(string $name): self
{
$user = App::make(static::class);
return $user->setName($name);
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
}
class App
{
protected static array $registry = [];
public static function bind($key, $value): void
{
static::$registry[$key] = $value;
}
public static function make(string $class)
{
return static::$registry[$class]
?? new $class();
}
}
Please or to participate in this conversation.