模拟/存根在 PHPUnit 中实现数组访问的类的对象

2022-01-25 00:00:00 php phpunit arrayaccess

这是我正在为其编写测试套件的类的构造函数(它扩展了 mysqli):

Here is the constructor of the class I am writing a test suite for (it extends mysqli):

function __construct(Config $c)
{
    // store config file
    $this->config = $c;

    // do mysqli constructor
    parent::__construct(
        $this->config['db_host'],
        $this->config['db_user'],
        $this->config['db_pass'],
        $this->config['db_dbname']
    );
}

传递给构造函数的Config类实现了php内置的arrayaccess接口:

The Config class passed to the constructor implements the arrayaccess interface built in to php:

class Config implements arrayaccess{...}

如何模拟/存根 Config 对象?我应该使用哪个?为什么?

How do I mock/stub the Config object? Which should I use and why?

提前致谢!

推荐答案

如果您可以轻松地从数组创建 Config 实例,那将是我的首选.虽然您希望在可行的情况下单独测试您的单元,但简单的协作者(例如 Config)应该足够安全,可以在测试中使用.设置它的代码可能比等效的模拟对象更容易读写(不易出错).

If you can easily create a Config instance from an array, that would be my preference. While you want to test your units in isolation where practical, simple collaborators such as Config should be safe enough to use in the test. The code to set it up will probably be easier to read and write (less error-prone) than the equivalent mock object.

$configValues = array(
    'db_host' => '...',
    'db_user' => '...',
    'db_pass' => '...',
    'db_dbname' => '...',
);
$config = new Config($configValues);

话虽如此,你模拟了一个实现 ArrayAccess 就像对待任何其他对象一样.

That being said, you mock an object implementing ArrayAccess just as you would any other object.

$config = $this->getMock('Config', array('offsetGet'));
$config->expects($this->any())
       ->method('offsetGet')
       ->will($this->returnCallback(
           function ($key) use ($configValues) {
               return $configValues[$key];
           }
       );

您也可以使用 at 来强制执行特定的访问顺序,但这样会使测试变得非常脆弱.

You can also use at to impose a specific order of access, but you'll make the test very brittle that way.

相关文章