Mockery1.0 参照渡しメソッド引数の振る舞いの保持

参照渡しメソッド引数の振る舞いの保持

PHPのクラスメソッドは参照私による引数を受け付けます。この場合、引数(メソッドに渡されたオリジナル変数への参照)に対する変化は、オリジナルの変数に反映されます。例をご覧ください。

class Foo
{

    public function bar(&$a)
    {
        $a++;
    }

}

$baz = 1;
$foo = new Foo;
$foo->bar($baz);

echo $baz; // 整数の2をechoする

上記の例の場合、$baz変数は参照渡し(引数の前の&文字に気が付きましたか?)でFoo::bar()メソッドに渡されています。bar()に変化が起きると、参照渡しではオリジナルの$bazに反映されます。

Mockeryは引数で参照の使用を分析できる箇所では、全てのメソッドを正しく処理します。(Reflectionを使用)クラスメソッドにより、どのように参照が操作されるかをモックするには、たとえば\Mockery::on()でクロージャ引数マッチャーが利用できます。複雑な引数のバリデーション章をご覧ください。

(PHPの制限により)Reflectionを使用したメソッドパラメータの分析ができない、内部PHPクラスは例外です。これを解決するには、\Mockery\Configuration::setInternalClassMethodParamMap()を使用し、内部クラスのメソッドパラメータを明示的に宣言します。

MongoCollection::insert()を使用した例をご覧ください。MongoCollectionはPECLのmongo拡張により提供される内部クラスです。insert()メソッドは最初の引数としてデータの配列を受け取り、オプショナルな配列を第2引数に受け取ります。(たとえば、参照渡しの引数がinsert()されることにより)新しい_idフィールドを含むために、オリジナルデータ配列は更新されます。(Mockeryへ引数が参照渡しされることを指示することにより)この振る舞いを引数マップの設定を使用することでモックできます。そして更新されることを期待しているメソッド引数へClosureをアタッチできます。

この参照渡しの動作が保持されていることを検査するPHPUnitのユニットテストをご覧ください。

public function testCanOverrideExpectedParametersOfInternalPHPClassesToPreserveRefs()
{
    \Mockery::getConfiguration()->setInternalClassMethodParamMap(
        'MongoCollection',
        'insert',
        array('&$data', '$options = array()')
    );
    $m = \Mockery::mock('MongoCollection');
    $m->shouldReceive('insert')->with(
        \Mockery::on(function(&$data) {
            if (!is_array($data)) return false;
            $data['_id'] = 123;
            return true;
        }),
        \Mockery::any()
    );

    $data = array('a'=>1,'b'=>2);
    $m->insert($data);

    $this->assertTrue(isset($data['_id']));
    $this->assertEquals(123, $data['_id']);

    \Mockery::resetContainer();
}

protectedメソッド

protectedメソッドを使用しており、参照渡しの振る舞いを保持しようとする場合は、異なったアプローチが必要です。

class Model
{
    public function test(&$data)
    {
        return $this->doTest($data);
    }

    protected function doTest(&$data)
    {
        $data['something'] = 'wrong';
        return $this;
    }
}

class Test extends \PHPUnit\Framework\TestCase
{
    public function testModel()
    {
        $mock = \Mockery::mock('Model[test]')->shouldAllowMockingProtectedMethods();

        $mock->shouldReceive('test')
            ->with(\Mockery::on(function(&$data) {
                $data['something'] = 'wrong';
                return true;
            }));

        $data = array('foo' => 'bar');

        $mock->test($data);
        $this->assertTrue(isset($data['something']));
        $this->assertEquals('wrong', $data['something']);
    }
}

これは極めてまれなケースですので、オリジナルのコードを多少変更する必要があります。protectedメソッドを呼び出すpublicメソッドを作成しました。それから、protectedメソッドの代わりに、publicメソッドをモックしています。この新しいpublicメソッドはprotectedメソッドのプロキシとして動作します。

ドキュメント章別ページ

概論

ヘッダー項目移動

注目:アイコン:ページ内リンク設置(リンクがないヘッダーへの移動では、リンクがある以前のヘッダーのハッシュをURLへ付加します。

移動

クリックで即時移動します。

バージョン

設定

適用ボタンクリック後に、全項目まとめて適用されます。

カラーテーマ
和文指定 Pagination
和文指定 Scaffold
Largeスクリーン表示幅
インデント
本文フォント
コードフォント
フォント適用確認

フォントの指定フィールドから、フォーカスが外れると、当ブロックの内容に反映されます。EnglishのDisplayもPreviewしてください。

フォント設定時、表示に不具合が出た場合、当サイトのクッキーを削除してください。

バックスラッシュを含むインライン\Code\Blockの例です。

以下はコードブロックの例です。

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * ユーザに関連する電話レコードを取得
     */
    public function phone()
    {
        return $this->hasOne('App\Phone');
    }
}

設定を保存する前に、表示が乱れないか必ず確認してください。CSSによるフォントファミリー指定の知識がない場合は、フォントを変更しないほうが良いでしょう。

キーボード・ショートカット

オープン操作

PDC

ページ(章)移動の左オフキャンバスオープン

HA

ヘッダー移動モーダルオープン

MS

移動/設定の右オフキャンバスオープン

ヘッダー移動

T

最初のヘッダーへ移動

E

最後のヘッダーへ移動

NJ

次ヘッダー(H2〜H4)へ移動

BK

前ヘッダー(H2〜H4)へ移動

その他

?

このヘルプページ表示
閉じる