Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Mockeryを読んでみたよ

chiroruxx
January 18, 2023

 Mockeryを読んでみたよ

第148回 PHP勉強会@東京のLTで使用したスライドです。

chiroruxx

January 18, 2023
Tweet

More Decks by chiroruxx

Other Decks in Technology

Transcript

  1. Mockeryを
    読んでみたよ
    2023/01/18
    第148回 PHP勉強会@東京

    View Slide

  2. コードリーディングの歴史
    第146回PHP勉強会
    ■ 柚⼝ ましろう さん
    第147回PHP勉強会
    ■ y_sone さん

    View Slide

  3. 流れにのっていくしかない!! 🌊

    View Slide

  4. > whoami
    ■ 名前: ちひろ/ちろ/前⽥
    ■ Twitter: @chiroruxxxx
    ■ 所属: 東京都⽴産業技術⼤学院⼤学
    産業技術専攻
    情報アーキテクチャコース
    追川PBL
    ■ テーマ: スクラムの理論と実践

    View Slide

  5. Mockery とは
    ■ モック(テストダブル)を作ってくれるライブラリ
    ■ ユニットテストとかで便利

    View Slide

  6. サンプルコード
    $user = Mockery::mock(User::class);
    $user->shouldReceive('getFullName')
    ->andReturn('テスト太郎');
    $decorator = new Decorator();
    $this->assertSame(
    '** テスト太郎 **',
    $decorator->decorate($user)
    );

    View Slide

  7. サンプルコード
    $user = Mockery::mock(User::class);
    $user->shouldReceive('getFullName')
    ->andReturn('テスト太郎');
    $decorator = new Decorator();
    $this->assertSame(
    '** テスト太郎 **',
    $decorator->decorate($user)
    );
    モックしたクラスは
    Userクラス︖

    View Slide

  8. サンプルコード
    $user = Mockery::mock(User::class);
    $user->shouldReceive('getFullName')
    ->andReturn('テスト太郎');
    $decorator = new Decorator();
    $this->assertSame(
    '** テスト太郎 **',
    $decorator->decorate($user)
    );
    モックしたクラスは
    Userクラス︖
    コンストラクタで
    引数が必要だけど︖

    View Slide

  9. サンプルコード
    $user = Mockery::mock(User::class);
    $user->shouldReceive('getFullName')
    ->andReturn('テスト太郎');
    $decorator = new Decorator();
    $this->assertSame(
    '** テスト太郎 **',
    $decorator->decorate($user)
    );
    モックしたクラスは
    Userクラス︖
    コンストラクタで
    引数が必要だけど︖
    こんなメソッド
    ないけど︖

    View Slide

  10. いったい何者なんだ・・・!!

    View Slide

  11. コードを読んで追っていくぞ 💪

    View Slide

  12. 今回の⽬的
    ■ Mockery::mock(User::class)
    で作成されるクラスが何者なのかを追ってく
    ■ 今回紹介しない話も、ブログに書いています
    – あしたからがんばる - Mockeryでのモックの作り⽅を調べてみた

    View Slide

  13. コードを読む
    ■ PhpStorm + XDebug で1⾏ずつ状態を確認しながら読める
    ■ 設定がちょっとだけ⾯倒
    – PHPerKaigi 2023で・・・?

    View Slide

  14. View Slide

  15. さっそく読んでいきます

    View Slide

  16. クラス定義の読み込み
    ■ ファイルを読み込んでる
    ■ 展開してみると・・・?
    $code = file_get_contents(__DIR__ . '/../Mock.php');

    View Slide

  17. クラス定義の読み込み
    $code = '
    class Mock implements MockInterface
    {
    // ...
    public function shouldReceive(...$methodNames)
    {
    // ...
    ';

    View Slide

  18. クラス定義の読み込み
    $code = '
    class Mock implements MockInterface
    {
    // ...
    public function shouldReceive(...$methodNames)
    {
    // ...
    ';
    💡 モックでメソッドが使える

    View Slide

  19. クラスの継承
    ■ Userクラスを継承するように書き換えてる
    $code = str_replace(
    "implements MockInterface",
    "extends ¥¥" . $className . " implements MockInterface",
    $code
    );

    View Slide

  20. クラスの継承
    $code = '
    class Mock extends ¥App¥Models¥User implements MockInterface
    {
    // ...
    public function shouldReceive(...$methodNames)
    {
    // ...
    ';
    💡 User 型として扱える

    View Slide

  21. クラスのロード
    ■ ええい! eval じゃい!
    ■ ただの⽂字列から実⾏可能な状態に
    eval("?>" . $definition->getCode());

    View Slide

  22. クラスのロード
    ■ クラスはできた!!インスタンスはまだ作ってない
    class Mock extends ¥App¥Models¥User implements MockInterface
    {
    // ...
    public function shouldReceive(...$methodNames)
    {
    // ...

    View Slide

  23. インスタンスの作成
    ■ リフレクションクラスを使って 💡コンストラクタ実⾏無しでインスタンスを作

    ■ ・・・⿊魔術だ!!
    $reflectionClass = $this->getReflectionClass($className);
    return $reflectionClass->newInstanceWithoutConstructor();

    View Slide

  24. インスタンスの作成

    View Slide

  25. まとめ
    ■ モックしたクラスは User クラス?
    – User クラスを継承しているのでUser型として扱える
    ■ shouldRecieve なんてメソッドは User クラスにないけど?
    – User クラスを継承した先で定義しているので使える
    ■ コンストラクタで引数が必要だけど?
    – リフレクションを使ってコンストラクタ無しで⽣成してる

    View Slide

  26. まとめ
    ■ みんなが使ってるあのライブラリも、蓋を開ければ案外ゴリ押し
    ■ みんなも気軽にゴリ押しでライブラリを作ってみては?

    View Slide