Php Mocking Laravel雄辩的模型-如何用mocky设置公共属性

Php Mocking Laravel雄辩的模型-如何用mocky设置公共属性,php,laravel,eloquent,mockery,Php,Laravel,Eloquent,Mockery,我想在PHPUnit测试中使用模拟对象(mockry)。模拟对象需要同时设置一些公共方法和一些公共属性。这门课是拉威尔雄辩的典范。我试过这个: $mock = Mockery::mock('User'); $mock->shouldReceive('hasRole')->once()->andReturn(true); //works fine $mock->roles = 2; //how to do this? currently returns an error $

我想在PHPUnit测试中使用模拟对象(mockry)。模拟对象需要同时设置一些公共方法和一些公共属性。这门课是拉威尔雄辩的典范。我试过这个:

$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()


模拟简单类时不会返回此错误,但在尝试模拟雄辩的模型时会返回此错误。我做错了什么?

试过这个吗?它应该涵盖你的问题

我要说的是实施这些

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));
这个后堂让您有机会在执行getRoles()时承诺一种格式,如果您执行SOLID OOP,它将是角色对象的数组,或者如果您更喜欢使用数组,那么至少您知道它始终是您得到的数组。

您尝试过这样做吗? 您可以尝试以下方法(未测试):


要回答您的问题,您还可以尝试以下方法:

$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);
但是,从您的代码片段来看,如果您正在编写单元测试,那么每个测试实际上应该只做一个断言:

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

如果要使用此值获取此属性,请使用它:

$mock->shouldReceive('getAttribute')
    ->with('role')
    ->andReturn(2);
如果您调用
$user->role
,您将得到-
2

$user
-它的
用户
模拟类)

这个答案有点晚了,但希望它能帮助一些人。您当前可以使用“alias”关键字在模拟的雄辩对象上设置静态属性:

$mocked_model = Mockery::mock('alias:Namespace\For\Model');
$mocked_model->foo = 'bar';
$this->assertEquals('bar', $mocked_model->foo);
这也有助于模拟外部供应商类,如一些条带对象

了解“别名”和“重载”关键字:
在这种情况下,您可以使用stdclass

$obj = new stdClass();
$obj->roles = 2;
$mock = Mockery::mock('User');
// return stdclass here.
$mock->shouldReceive('hasRole')->once()->andReturn($obj);
$mock->roles = 2;
$this->assertEquals(2, $mock->roles);

Spy是您在这方面的朋友:

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

Laravel 5.3中的部分模拟

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

是的,我读过这一页,但没有提供示例。当我尝试set()时,我得到BadMethodCallException:MethodMockery\u 0\u User::set()在此模拟对象上不存在。我真正想要的是一个示例。BadMethodCallException:Method Mockery_0_User::setAttribute()在此模拟对象上不存在。更新了我的响应,当您使用用户对象时,它将在IDE中为您提供完整的代码谢谢,但这不只是更改用户类的实现以添加getter和setter吗?虽然这可能是一个解决办法,但我不知道这是如何回答最初的问题的。知道这是来自Lavarel的持久化对象可能很好:>现在根据Mockery的说法,注入公共变量是可以的,但它不支持神奇函数,我对Lavarel的了解不够,无法说明问题所在。它看起来确实像->角色被转换成->setAttribute('roles',$value);但我可能错了。也许这是一个愚蠢的问题——但取决于你在测试什么,你甚至需要一个模拟对象吗?如果您正在测试hasRole()方法,为什么不使用$mock=newuser$模拟->角色=2;测试一下?例如,如果我在测试访问者/演示者等,我只会选择一个合适的对象,而不是模拟setAttribute等。@Apemantus谢谢。我正在测试一个有关系的模型(一个用户有许多角色)。我不知道如何在不保存到数据库的情况下设置关系。我正在尝试编写一个不需要接触数据库的测试。好的。我还没有测试我们的关系,但是可以使用('roles)->andReturn(2)执行$mock->shouldReceive('setAttribute')->但这只会返回整数。如果您愿意,我想您可以返回角色模型的第二个模拟,如果您的对象需要该模型类的实例,您就不能返回。我得到了未定义的属性:Mockery\compositeexpection::$Role由于公共静态方法,在执行模拟时,我得到了类似的
错误异常:未定义属性:App\User:$Role
。在这种情况下,我的解决方案是直接设置道具,如
$mock->role=2
。(PHP7.1、PHPUnit 6.5.14、Mockry 1.2.2、laravel测试用例<代码>照明\基础\测试\测试用例)我收到错误“无法加载模拟应用程序\模型\用户,类已存在”。
$mock = Mockery::mock(App\User::class)->makePartial();
$mock->shouldReceive('hasRole')->once()->andReturn(true);
$mock->roles = 2; 
$this->assertEquals(2, $mock->roles);