web-dev-qa-db-ja.com

モッキングLaravel Eloquentモデル-Mockeryでパブリックプロパティを設定する方法

PHPUnitテストでモックオブジェクト(Mockery)を使用したいと思います。モックオブジェクトには、いくつかのパブリックメソッドといくつかのパブリックプロパティセットの両方が必要です。クラスはLaravel雄弁なモデルです。私はこれを試しました:

$mock = Mockery::mock('User');
$mock->shouldReceive('hasRole')->once()->andReturn(true); //works fine
$mock->roles = 2; //how to do this? currently returns an error
$this->assertTrue(someTest($mock));

...しかし、パブリックプロパティを設定すると、次のエラーが返されます。

BadMethodCallException:メソッドMockery_0_User :: setAttribute()がこのモックオブジェクトに存在しません

このエラーは、単純なクラスをモックする場合には返されませんが、Eloquentモデルをモックしようとすると返されます。何が悪いのですか?

23
mtmacdonald

この値でこのプロパティを取得するには、次のように使用します。

$mock ->shouldReceive('getAttribute')
    ->with('role')
    ->andReturn(2);

$user->roleを呼び出すと、-2$user-Userモッククラス)が得られます。

13
Joyful

この答えは少し遅いですが、うまくいけば誰かを助けるでしょう。現在、「alias」キーワードを使用して、モックされたEloquentオブジェクトに静的プロパティを設定できます。

$mocked_model = Mockery::mock('alias:Namespace\For\Model');
$mocked_model->foo = 'bar';
$this->assertEquals('bar', $mocked_model->foo);

これは、いくつかのStripeオブジェクトなどの外部ベンダークラスをモックする場合にも役立ちます。

「エイリアス」および「オーバーロード」のキーワードについてお読みください: http://docs.mockery.io/en/latest/reference/startup_methods.html

6
Fancypants_MD

あなたの質問に答えるために、次のようなことも試すことができます:

$mock = Mockery::mock('User');
$mock->shouldReceive('hasRole')->once()->andReturn(true); //works fine
$mock->shouldReceive('setAttribute')->passthru();
$mock->roles = 2; 

$mock->shouldReceive('getAttribute')->passthru();
$this->assertEquals(2, $mock->roles);

または、seblazeで提案されているように、部分モックを使用します。

$mock = Mockery::mock('User[hasRole]');
$mock->shouldReceive('hasRole')->once()->andReturn(true);
$mock->roles = 2; 
$this->assertEquals(2, $mock->roles);

ただし、コードスニペットから、ユニットテストを作成している場合は、実際には各テストにつき1つのアサーションのみを作成する必要があります。

function test_someFunctionWhichCallsHasRole_CallsHasRole() {
    $mock = Mockery::mock('User');
    $mock->shouldReceive('hasRole')->once();

    $mock->someFunctionWhichCallsHasRole();
}

function test_someFunctionWhichCallsHasRole_hasRoleReturnsTrue_ReturnsTrue() {
    $mock = Mockery::mock('User');
    $mock->shouldReceive('hasRole')->once()->andReturn(true);

    $result = $mock->someFunctionWhichCallsHasRole();

    $this->assertTrue($result);
}        
2
awei

Spyはあなたの友達です:

$mock = Mockery::spy('User');
$mock->shouldReceive('hasRole')->once()->andReturn(true);
$mock->roles = 2;
$this->assertTrue(someTest($mock));
1

これを試しましたか?問題をカバーする必要があります。

https://github.com/padraic/mockery/blob/master/docs/11-MOCKING-PUBLIC-PROPERTIES.md

これらを実装すると思います

protected $roles = array();

public function setRoles($roles)
{
    $this->roles = $roles;
}

public function addRole($role)
{
    $this->roles[] = $role;
}

次に、以下を使用してテストできます。

$mock = Mockery::mock('User');
$mock->shouldReceive('hasRole')->once()->andReturn(true);
$mock->addRole(2);
$this->assertTrue(someTest($mock));

この後陣は、あなたがSOLID OOPを実行する場合、または少なくとも配列を使用する場合、少なくともあなたがそれは常にあなたが得る配列であることを知っています。

0
Oldek

Laravel 5.3の部分モック

$mock = Mockery::mock(App\User::class)->makePartial();
$mock->shouldReceive('hasRole')->once()->andReturn(true);
$mock->roles = 2; 
$this->assertEquals(2, $mock->roles);
0
aCiD

部分的なモック しようとしましたか?あなたは(テストされていません)のようなものを試すことができます:

$mock = Mockery::mock('User[hasRole]');
$mock->shouldReceive('hasRole')->once()->andReturn(true);
$mock->roles = 2; 
$this->assertTrue(someTest($mock));
0
Paul Bele