--> -->

skimemo


Laravel-20181223 のバックアップ(No.1)


_ 外部クラスの呼び出しをMockする

これは12/20分:Laravel-20181220の続きです。

12/20時点ではoverloadがうまくいかず、外部クラス参照のMockを上手く作れなかったのですが、原因が判明しましたのでその経緯を記述します。

_ 問題1: overloadに失敗する

テストコードに以下のように書きます。

  1
$mock = \Mockery::mock('overload:SomeNamespace\SubClass'); 

以下のエラーとなります。

Mockery\Exception\RuntimeException: Could not load mock SomeNamespace\SubClass, class already exists

当該テストコードではuseもnewもしていないのですが、これが出ます。
そこで、参考ページ*1の通り、アノテーションを入れます。

  1
  2
  3
  4
  5
  6
/**
 * @runInSeparateProcess
 * @preserveGlobalState disabled
 */
public function testMyClass() {
    : 

runInSeparateProcess : 別プロセスで動かします
preserveGlobalState : 前項に関連して親プロセスの状態維持を無効にします

_ 問題2: $nameが無いと言われる

すると今度は以下のようなエラーが出ました。

PHPUnit_Framework_Exception: PHPUnit_Framework_TestCase::$name must not be null.

実はこのテストコードは、PHPUnit_Framework_TestCaseを継承しておらず、TestCase(PHPUnit_Framework_TestCase<-Illuminate\Foundation\Testing\TestCase<-Tests\TestCase)を継承しています。(Laravelの標準的な書き方)
ところがこのTestCaseに以下のようなconstructorを書いていました。

  1
  2
  3
  4
public function __construct() {
    parent::__construct();
    // ごにょごにょ
} 

Laravelを始めた頃(言い訳)、特に誰(phpStorm)にも怒られなかったのでこのまま安易に書いていましたが、親クラスのコンストラクタは任意のパラメータとして$name, $data, $dataNameが定義されています。従って、ここは以下のように書くべきでした。*2

  1
  2
  3
  4
public function __construct($name = null, array $data = [], $dataName = '') {
    parent::__construct($name, $data, $dataName);
    // ごにょごにょ
} 

これで無事overloadのテストを通すことができました。


 


MockeryでoverloadをつかってテストしたらCould not load mockとか言われる件
https://qiita.com/kadoyau/items/13d515f42a943a6c6c1a


PHPUnit_Framework_Exception: PHPUnit_Framework_TestCase::$name must not be null
https://stackoverflow.com/a/41534986/5150050