在 phpunit 中模拟 class

Mock class in phpunit

我终于进入 PHP 单元测试(是的,迟到总比不到好!)

我有一个 Utility class 可以做一些事情,包括验证用户对网络服务的访问。 Utility::authenticate 方法采用 Settings 对象,其中包含由 authenticate 检查的用户名等。

所以在我的测试中,我模拟了一个 Settings 对象,如下所示:

$settings = $this->getMock('Settings', array('getSettings'));

$settings->method('getSettings')
    ->willReturn([
        'USERNAME' => 'testuser',
        'SERVER' => 'testserver'
    ]);

$mock = $settings->getSettings();

到目前为止一切顺利,但是当我尝试将模拟对象传递给 authenticate 时,它会抛出一个错误:

$this->assertEquals($testvalue, Utilities::authenticate($settings));
Argument 1 passed to Utilities::authenticate() must be an instance of Settings, instance of Mock_Settings_d0361624 given

我如何模拟 Settings 对象,使其看起来是 Utilities class 的 "real" 对象?

编辑以添加 getSettings 函数:

class Settings {

private $settings;
private static $instance;

public function __construct(){
    $configfile = "config/config.ini";
    //if( !$this->settings = parse_ini_file( $configfile, true ) ){
        //die('SETTINGS OBJECT NOT FOUND OR COULD NOT BE PARSEd');
    //}
}
/**
 * @return Settings
 */
public static function getSettings(){
    if ( !self::$instance ){
        self::$instance = new Settings();
    }
    if(!utilities::authenticate(self::$instance)) die('AUTHENTICATION FAILED-- CHECK API KEY');
    return self::$instance;
}

当您使用错误的类名创建对象时会出现此错误消息。检查 getMock 方法传递带有命名空间的完整类名,例如:

$settings = $this->getMock('Acme\DemoBundle\Model\Settings', array('getSettings'));

希望对您有所帮助

编辑

该方法是静态的,phpunit 库不支持 mock static 方法 here and here

所以你可以使用一些 mockking 框架,比如 Phake that support mocking static method as described here。作为工作示例:

public function test_authenticate()
{
    $settings = \Phake::mock('Acme\DemoBundle\Model\Settings');

    \Phake::whenStatic($settings)
        ->getSettings()
        ->thenReturn([
            'USERNAME' => 'testuser',
            'SERVER' => 'testserver'
        ]);

    $mock = $settings->getSettings();

    $testvalue = true;
    $this->assertEquals($testvalue, Utilities::authenticate($settings));
}