5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

コンストラクタインジェクションされたクラスのprivate メソッドでもテストファーストしたい

Last updated at Posted at 2019-04-13

テストファーストで開発するなら手を動かしながら軽い気持ちで書きたい。
例えそのクラスがprivateメソッドで依存関係があっても。

実装

例えば文字列を加工する処理のテストをTestクラスで実装する。

ServiceTest.php
    // テストしたいメソッド
    private function convertWord(string $keyword): string
    {
        $cv_word = trim($keyword);
        $cv_word = mb_convert_kana($cv_word,'Kas');
        return $cv_word;
    }

    public function testConvertWord()
    {
        // トリム処理 半角カナ->全角カナ(K)
        $word = ' 全角カタカナ ';
        $result = $this->convertWord($word);
        $this->assertSame('全角カタカナ', $result);
        // 全角英数字->半角英数字(a) 全角スペース->半角スペース(s)
        $word = 'Aiueo123 ';
        $result = $this->convertWord($word);
        $this->assertSame('Aiueo123 ', $result);
    }

移動方法

しかしこのメソッドは別のクラスで使うために書いてるので、メソッドを移動させる。

Service.php
    private $repository;
    public function __construct(RepositoryInterface $repository)
    {
        $this->repository = $repository;
    }

    private function convertWord(string $keyword): string
    {
        $cv_word = trim($keyword);
        $cv_word = mb_convert_kana($cv_word,'Kas');
        return $cv_word;
    }

移動させたらprivateメソッドなのでReflectionクラスを使ってprivateメソッドにアクセスできるようにして、
コンストラクタを起動せずにインスタンスを作成する。

ServiceTest.php
    public function testConvertWord()
    {
        $reflection = new \ReflectionClass(Service::class);
        $method = $reflection->getMethod('convertWord');
        $method->setAccessible(true);
        $not_construct_service = $reflection->newInstanceWithoutConstructor();

        // トリム処理 半角カナ->全角カナ(K)
        $word = ' 全角カタカナ ';
        // $result = $this->convertWord($word);
        $result = $method->invoke($not_construct_service, $word);
        $this->assertSame('全角カタカナ', $result);
        // 全角英数字->半角英数字(a) 全角スペース->半角スペース(s)
        $word = 'Aiueo123 ';
        $result = $method->invoke($not_construct_service, $word);
        $this->assertSame('Aiueo123 ', $result);
    }

移動できたことを確認するためにphpunitを起動。

Time: 757 ms, Memory: 8.00 MB

OK (1 test, 2 assertions)

Process finished with exit code 0

まとめ

privateメソッドをテストするのは、クラス設計が悪い、別クラスやヘルパーとして切り出せとか賛否両論あるかもだけど、スコープを抑えたいとかどうしても設計を変更できない場合などもあると思うので知識として知っておいて良いと思う。まあ他言語だとReflectionクラスが無いとかあるし、後に設計変更したいと思っても、テストがあることで安全に変更できるので、まずは動くものとテストを書きたい。

(参考)
https://qiita.com/suin/items/a1c3d96050cb7e51424d
https://qiita.com/mpyw/items/b3d974c073e6484d51a4

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?