動作環境
PHP 7.2
PHPUnit 6.5.14
Mockery 1.2.2
やりたいこと
Mockeryでモック化したUserRepositoryクラスのメソッドisExist
の動作を引数によって切り替えたい
isExistメソッドの役割:指定されたユーザIDが存在している場合 true 存在していない場合 false を返す
コード
interface UserRepository
{
/**
* @param UserId $userId
* @return bool true:ユーザが存在する false:ユーザが存在しない
*/
public function isExist(UserId $userId): bool;
}
class UserId
{
/**
* @var int
*/
protected $id;
/**
* UserId constructor.
* @param int $id
*/
public function __construct(int $id)
{
$this->id = $id;
}
/**
* @return int
*/
public function getId(): int
{
return $this->id;
}
}
//~~~~~~~~~ 以下テストケース内
$mockUserRepository = \Mockery::mock(UserRepository::class);
$mockUserRepository->shouldReceive('isExist')
->byDefault()
->andReturn(true);
$mockUserRepository->shouldReceive('isExist')
->with(\Mockery::on(function (UserId $userId) {
if ($userId->getId() === 999) { //ユーザIDが 999 の場合に andReturn に指定された値を返却する
return true;
}
return false;
}))
->andReturn(false);
$this->assertTrue($this->mockUserRepository->isExist(new UserId(1))); // OK
$this->assertFalse($this->mockUserRepository->isExist(new UserId(999))); // OK
ポイント
Mockeryのwith
メソッドは通常値を設定するだけで、動作を切り替えたりできますが、
今回のように「オブジェクトが引数」となる場合はだたwith
を使うだけだと想定どおりに動作してくれません。
誤りのケース
$mockUserRepository->shouldReceive('isExist')
->byDefault()
->andReturn(true);
$mockUserRepository->shouldReceive('isExist')
->with(new UserId(999)) // new UserId(999) === new UserId(999) → false
->andReturn(false);
$this->assertTrue($this->mockUserRepository->isExist(new UserId(1))); // OK
$this->assertFalse($this->mockUserRepository->isExist(new UserId(999))); // NG defaultのほうが呼ばれてしまっている