1. ホーム
  2. php

[解決済み] PHPUnitでプライベートメソッドをモックする

2023-07-05 16:20:13

質問

PHPUnit を使ってクラス内のプライベートメソッドをモックする方法について質問があります。例を挙げて紹介します。

class A {
  public function b() { 
    // some code
    $this->c(); 
    // some more code
  }

  private function c(){ 
    // some code
  }
}

をテストするために、プライベートメソッドの結果をどのようにスタブすればよいですか? もう少しコード の部分をテストすることができます。

を読んで部分的に解決 はこちら

どのように解決するのですか?

通常、private & protected メソッドを直接テストしたりモックしたりしないだけです。

あなたがテストしたいのは public API です。他のすべては、あなたのクラスの実装の詳細であり、あなたがそれを変更した場合、あなたのテストは "break"べきではありません。

また、パブリックAPIを呼び出しても実行できないコードがクラス内にあるかもしれないので、"100%のコードカバレッジが得られない"ということに気づいたときにも役立ちます。


通常、このようなことはしたくありません。

しかし、もしあなたのクラスがこのようなものだとしたら。

class a {

    public function b() {
        return 5 + $this->c();
    }

    private function c() {
        return mt_rand(1,3);
    }
}

random"関数はグローバルな状態であり、それをテストすることができないので、c()をモックアウトする必要性を理解することができます。

きれいな(quot;verbose;overcomplicated-maybe;i-like-it-usually")解決策。

class a {

    public function __construct(RandomGenerator $foo) {
        $this->foo = $foo;
    }

    public function b() {
        return 5 + $this->c();
    }

    private function c() {
        return $this->foo->rand(1,3);
    }
}

これで、グローバルが含まれないので、モックを作成する必要がなくなり、きれいにテストができるようになりました。


プライベート関数からグローバル状態を削除したくない、または削除できない場合(悪いこと悪い現実、または悪いことの定義が異なるかもしれません)、次のようにします。 ができます。 モックに対してテストしてください。

// maybe set the function protected for this to work
$testMe = $this->getMock("a", array("c"));
$testMe->expects($this->once())->method("c")->will($this->returnValue(123123));

で、このモックに対してテストを実行します。モックから取り出す関数は "c()" だけです。


Pragmatic Unit Testing"の本を引用すると。

一般的に、テストのためにカプセル化を壊したくはないでしょう(あるいは、ママがよく言っていたように、" don't expose your privates!" )。ほとんどの場合、パブリックメソッドを実行することで、クラスをテストすることができるはずです。プライベートまたは保護されたアクセスの背後に隠されている重要な機能がある場合、それは別のクラスが外に出ようと奮闘しているという警告サインかもしれません。


もう少し Why you don't want test private methods.