PHPテストの引数キャプチャ


あなたはすでにあなたのテストのスキルに自信を持っているすべてのチームメイトは、お尻とスタブについて話しうらやましい.しかし今、あなたは新しい挑戦に直面している、あなただけの引数のいくつかのプロパティを確認する必要がある場合、それ以外の場合、あなたのテストは惨めに失敗します.


晴れの日
あなたの仕事はシンプルなユーザ登録機能を実装することでした.良いプログラマとして、これを使用する計画Repository あなたが永続的な層を分離し、必要に応じて単体テストでそれを模擬することができますので、パターン.


ユーザクラス
簡単ではない、右?
final class User
{
    public function __construct(
        private string $id,
        private string $name)
    {
    }

    public function getId(): string
    {
        return $this->id;
    }

    public function getName(): string
    {
        return $this->name;
    }
}

ユーザーリポジトリ
何か固執しないでください、しかし、それを偽りましょう.
final class UserRepository
{
    public function save(User $user): void
    {
        echo sprintf('Persisted user with id %s and name %s', $user->getId(), $user->getName());
    }
}

ユーザサービス
今、我々はいくつかのプロットねじれている!いくつかの狂気の要件が上記から到着し、それはid フィールドは乱数でなければなりません.さて、これを実現する方法はたくさんあります.
final class UserService
{
    public function __construct(private UserRepository $repository) { }

    public function createNewUser(string $name): void
    {
        $user = new User(uniqid(), $name);

        $this->repository->save($user);
    }
}
クール、すべてが働いている.

待って、テストを忘れないようにしましょう

私たちは、いつUserService を作成するUser , if the UserRepository が正しく呼び出されます.我々は永続性については気にしないので、我々はちょうどリポジトリをモックアップすることができますし、すべてがうまく動作するはずです.
public function testFailing(): void
{
    $repository = $this->createMock(UserRepository::class);

    $userService = new UserService($repository);

    $repository
        ->expects($this->once())
        ->method('save')
        ->with(new User('not so random id', 'user'));

    $userService->createNewUser('user');
}
テストまで失敗しますUser with not so random id 引数にマッチしませんUserRepository これは新しいユーザが作成されるたびに異なるIDを持つ.

レスキューに引数をキャプチャ!
Javaでは、同じ機能を有効にしますMockito :

Argument Capture allows us to create assertions on certain values of the arguments, instead of testing the equality for the whole object.


例では、テストする必要はありませんid 値は、乱暴なので、それ自体がPHPを使用して生成されているuniqid 関数.
最後に、これはどのように使用してテストですargument capture 以下のようになります.
public function testRepositoryShouldCreateUserWithCorrectName(): void
{
    $repository = $this->createMock(UserRepository::class);

    $userService = new UserService($repository);

    $repository
        ->expects($this->once())
        ->method('save')
        ->will($this->returnCallback(function($user) {
            self::assertEquals('user', $user->getName());
        }));

    $userService->createNewUser('user');
}
これを読んでのおかげで、あなたのテストを楽しんだと幸運を期待!