Je veux utiliser un objet fictif (Mockery) dans mon test PHPUnit. L'objet fictif doit avoir à la fois des méthodes publiques et des propriétés publiques définies. La classe est un modèle Laravel Eloquent. J'ai essayé ceci:
$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));
... mais la définition de la propriété publique renvoie cette erreur:
BadMethodCallException: La méthode Mockery_0_User :: setAttribute () n'existe pas sur cet objet fictif
Cette erreur n'est pas renvoyée lorsque vous vous moquez d'une classe simple, mais lorsque je tente de simuler un modèle Eloquent. Qu'est-ce que je fais mal?
Si vous voulez obtenir cette propriété avec cette valeur, utilisez-la simplement:
$mock ->shouldReceive('getAttribute')
->with('role')
->andReturn(2);
Si vous appelez $user->role
, vous obtiendrez - 2
($user
- sa classe User
)
Cette réponse est un peu tardive mais j'espère que cela aidera quelqu'un. Vous pouvez actuellement définir une propriété statique sur les objets Eloquent simulés en utilisant le mot clé 'alias':
$mocked_model = Mockery::mock('alias:Namespace\For\Model');
$mocked_model->foo = 'bar';
$this->assertEquals('bar', $mocked_model->foo);
Cela est également utile pour se moquer des classes de fournisseurs externes telles que certains objets Stripe.
Lisez à propos des mots clés 'alias' et 'overload': http://docs.mockery.io/en/latest/reference/startup_methods.html
Pour répondre à votre question, vous pouvez également essayer quelque chose comme ceci:
$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);
Ou, comme suggéré par seblaze, utilisez une simulation partielle:
$mock = Mockery::mock('User[hasRole]');
$mock->shouldReceive('hasRole')->once()->andReturn(true);
$mock->roles = 2;
$this->assertEquals(2, $mock->roles);
Cependant, à partir de votre extrait de code, si vous écrivez des tests unitaires, vous ne devez en réalité faire qu'une affirmation par test:
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 est votre ami à ce sujet:
$mock = Mockery::spy('User');
$mock->shouldReceive('hasRole')->once()->andReturn(true);
$mock->roles = 2;
$this->assertTrue(someTest($mock));
J'ai essayé ça? Il devrait couvrir votre problème.
https://github.com/padraic/mockery/blob/master/docs/11-MOCKING-PUBLIC-PROPERTIES.md
Je dirais mettre en œuvre ces
protected $roles = array();
public function setRoles($roles)
{
$this->roles = $roles;
}
public function addRole($role)
{
$this->roles[] = $role;
}
Ensuite, vous pouvez tester en utilisant:
$mock = Mockery::mock('User');
$mock->shouldReceive('hasRole')->once()->andReturn(true);
$mock->addRole(2);
$this->assertTrue(someTest($mock));
Cette abside vous donne la possibilité de promettre un format lorsque vous effectuez un getRoles () qui serait un tableau d'objet Role si vous faites SOLID OOP, ou si vous utilisez plutôt un tableau, alors au moins, vous savez qu'il est toujours un tableau que vous obtenez.
Simulation partielle dans Laravel 5.3
$mock = Mockery::mock(App\User::class)->makePartial();
$mock->shouldReceive('hasRole')->once()->andReturn(true);
$mock->roles = 2;
$this->assertEquals(2, $mock->roles);
Avez-vous essayé de faire des faux partiels ? Vous pouvez essayer quelque chose comme (NON TESTÉ):
$mock = Mockery::mock('User[hasRole]');
$mock->shouldReceive('hasRole')->once()->andReturn(true);
$mock->roles = 2;
$this->assertTrue(someTest($mock));