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モデルをモックしようとすると返されます。何が悪いのですか?
この値でこのプロパティを取得するには、次のように使用します。
$mock ->shouldReceive('getAttribute')
->with('role')
->andReturn(2);
$user->role
を呼び出すと、-2
($user
-User
モッククラス)が得られます。
この答えは少し遅いですが、うまくいけば誰かを助けるでしょう。現在、「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
あなたの質問に答えるために、次のようなことも試すことができます:
$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);
}
Spyはあなたの友達です:
$mock = Mockery::spy('User');
$mock->shouldReceive('hasRole')->once()->andReturn(true);
$mock->roles = 2;
$this->assertTrue(someTest($mock));
これを試しましたか?問題をカバーする必要があります。
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を実行する場合、または少なくとも配列を使用する場合、少なくともあなたがそれは常にあなたが得る配列であることを知っています。
Laravel 5.3の部分モック
$mock = Mockery::mock(App\User::class)->makePartial();
$mock->shouldReceive('hasRole')->once()->andReturn(true);
$mock->roles = 2;
$this->assertEquals(2, $mock->roles);
部分的なモック しようとしましたか?あなたは(テストされていません)のようなものを試すことができます:
$mock = Mockery::mock('User[hasRole]');
$mock->shouldReceive('hasRole')->once()->andReturn(true);
$mock->roles = 2;
$this->assertTrue(someTest($mock));