如何在PHPUnit中模拟返回新类的参数?

如何在PHPUnit中模拟返回新类的参数?,php,unit-testing,mocking,arguments,phpunit,Php,Unit Testing,Mocking,Arguments,Phpunit,我对一行代码有问题,比如: $user->has('roles', ORM::factory('role', array('name' => 'unverified'))) 我可以模拟第一个参数,但只能断言第二个参数返回一个类。在某些类中,我多次使用has,并且需要能够正确地测试它们。为了清楚起见,我需要确认第二个参数的工厂方法中传递了“unverified”。非常感谢您的帮助 我正在测试的类: <?php /** * Policy class to determine i

我对一行代码有问题,比如:

$user->has('roles', ORM::factory('role', array('name' => 'unverified')))
我可以模拟第一个参数,但只能断言第二个参数返回一个类。在某些类中,我多次使用
has
,并且需要能够正确地测试它们。为了清楚起见,我需要确认第二个参数的工厂方法中传递了“unverified”。非常感谢您的帮助

我正在测试的类:

<?php
/**
 * Policy class to determine if a user can upload a file.
 */
class Policy_File_Upload extends Policy
{
    const NOT_LOGGED_IN = 1;
    const NOT_VERIFIED = 2;

    public function execute(Model_ACL_User $user, array $extra = NULL)
    {
        if ($user->can('login'))
        {
            return self::NOT_LOGGED_IN;
        }
        elseif ($user->has('roles', ORM::factory('role', array('name' => 'unverified'))))
        {
            return self::NOT_VERIFIED;
        }

        return TRUE;
    }
}
为了清楚起见,我需要确认第二个参数的工厂方法中传递了“unverified”


为了清楚起见,我需要确认第二个参数的工厂方法中传递了“unverified”


您实际上可以使用for PHP中的函数对传递给模拟方法的参数进行验证

本例假设您能够检查$factoriedRole上的名称,显然需要根据ORM堆栈的工作方式更改该部分

我同意edorian关于静力学的观点。如果可能的话,我总是希望重新设计代码而不需要静态,但有时这是不可能的,在这种情况下,这是一个可行的解决方案


您实际上可以使用for PHP中的函数对传递给模拟方法的参数进行验证

本例假设您能够检查$factoriedRole上的名称,显然需要根据ORM堆栈的工作方式更改该部分

我同意edorian关于静力学的观点。如果可能的话,我总是希望重新设计代码而不需要静态,但有时这是不可能的,在这种情况下,这是一个可行的解决方案


您可以始终按照数据驱动的方式为每种情况准备测试数据,并验证调用函数的结果。最后,您不会太在意
'unverified'
被传递到
ORM::factory()
,而是基于输入从
execute()
得到正确的结果


测试实现细节会使测试变得脆弱且难以编写。如果您可以测试结果,那么当您改变获得结果的方式时,您的测试不会中断。为所有用例组合一个数据集可能需要更长的时间,但它通常可以在测试之间共享。

您可以始终按照数据驱动的方式为每个用例准备测试数据,并验证调用函数的结果。最后,您不会太在意
'unverified'
被传递到
ORM::factory()
,而是基于输入从
execute()
得到正确的结果


测试实现细节会使测试变得脆弱且难以编写。如果您可以测试结果,那么当您改变获得结果的方式时,您的测试不会中断。为所有用例组合一个数据集可能需要更长的时间,但它通常可以在测试之间共享。

当然,但我需要一种方法将数据传递给函数,以确保逻辑正常工作。因此,根据您的建议,我可以设置用户应该拥有的角色数组并断言正确的结果。是的,要测试
未验证的情况,您需要传入一个具有单个角色
“未验证”的用户。如果
ORM::factory()
被破坏,此测试也将被错误地报告为已破坏,但是
ORM
测试应该为您提供真正问题的线索。根据具体情况,我会混合使用所有这些技术,但我更喜欢数据驱动测试,因为它们更严格地以结果为导向。我的第一句话“抱歉”误解了你。我知道你是说我需要创建数据集进行测试。我也将对此进行研究。当然,但我需要一种方法将数据传递给函数,以确保逻辑正常工作。因此,根据您的建议,我可以设置用户应该拥有的角色数组并断言正确的结果。是的,要测试
未验证的情况,您需要传入一个具有单个角色
“未验证”的用户。如果
ORM::factory()
被破坏,此测试也将被错误地报告为已破坏,但是
ORM
测试应该为您提供真正问题的线索。根据具体情况,我会混合使用所有这些技术,但我更喜欢数据驱动测试,因为它们更严格地以结果为导向。我的第一句话“抱歉”误解了你。我知道你是说我需要创建数据集进行测试。我也会调查这件事。
public function test_guest()
{
    // User mock
    $user = $this->getMock('Model_User', array('can', 'has'), array(), '', FALSE);
    $user->expects($this->any())->method('can')->with('login')->will($this->returnValue(TRUE));
    $user->expects($this->any())->method('has')->with('roles', $this->logicalOr
    (

    ))
    ->will($this->returnCallback(array($this, 'roles')));


    $policy = new Policy_File_Upload;

    $this->assertSame(Policy_File_Upload::NOT_VERIFIED, $policy->execute($user));
}
<?php

public function execute(Model_ACL_User $user, array $extra = NULL)
    [...] ORM::factory('role', array('name' => 'unverified')) [...]
public function test_guest()
{
    // User mock
    $user = Phake::mock('Model_User');
    when($user)->can('login')->thenReturn(FALSE);
    when($user)->has('roles', $this->anything())->thenGetReturnByLambda(array($this, 'roles'));

    $policy = new Policy_File_Upload;

    $this->assertSame(Policy_File_Upload::NOT_VERIFIED, $policy->execute($user));

    Phake::verify($user)->has('roles', Phake::capture($factoriedRole));

    $this->assertEquals('unverified', $factoriedRole->get('name'));
}