web-dev-qa-db-fra.com

Railleur Laravel Modèles éloquents - comment définir une propriété publique avec Mockery

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?

22
mtmacdonald

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)

13
Joyful

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

5
Fancypants_MD

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);
}        
2
awei

Spy est votre ami à ce sujet:

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

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.

0
Oldek

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);
0
aCiD

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));
0
Paul Bele