模拟/存根在 PHPUnit 中实现数组访问的类的对象
Posted
技术标签:
【中文标题】模拟/存根在 PHPUnit 中实现数组访问的类的对象【英文标题】:Mocking/Stubbing an Object of a class that implements arrayaccess in PHPUnit 【发布时间】:2012-05-23 08:16:30 【问题描述】:这是我正在为其编写测试套件的类的构造函数(它扩展了 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
接口:
class Config implements arrayaccess...
如何模拟/存根Config
对象?我应该使用哪个?为什么?
提前致谢!
【问题讨论】:
【参考方案1】:如果您可以轻松地从数组创建 Config
实例,那将是我的首选。虽然您想在可行的情况下单独测试您的单元,但简单的协作者(例如 Config
)应该足够安全,可以在测试中使用。设置它的代码可能比等效的模拟对象更容易读写(不易出错)。
$configValues = array(
'db_host' => '...',
'db_user' => '...',
'db_pass' => '...',
'db_dbname' => '...',
);
$config = new Config($configValues);
话虽如此,您可以像模拟任何其他对象一样模拟实现ArrayAccess
的对象。
$config = $this->getMock('Config', array('offsetGet'));
$config->expects($this->any())
->method('offsetGet')
->will($this->returnCallback(
function ($key) use ($configValues)
return $configValues[$key];
);
您也可以使用at
来强制执行特定的访问顺序,但这样会使测试变得非常脆弱。
【讨论】:
你甚至可以轻松地做到这一点,但使用数组:-)【参考方案2】:在提出问题 8 年后,在第一次回答问题 5 年后,我遇到了同样的问题并得出了类似的结论。这就是我所做的,这与大卫接受的答案的第二部分基本相同,只是我使用的是更高版本的 PHPUnit。
基本上你可以模拟ArrayAccess
接口方法。只需要记住,您可能想要同时模拟 offsetGet
和 offsetExists
(在使用它之前,您应该始终检查数组键是否存在,否则您可能会遇到 E_NOTICE
错误和代码中不可预知的行为,如果它没有'不存在)。
$thingyWithArrayAccess = $this->createMock(ThingyWithArrayAccess::class);
$thingyWithArrayAccess->method('offsetGet')
->with('your-offset-here')
->willReturn('test-value-1');
$thingyWithArrayAccess->method('offsetExists')
->with($'your-offset-here')
->willReturn(true);
当然,您可以在测试中使用真正的数组,例如
$theArray = [
'your-offset-here-1' => 'your-mock-value-for-offset-1',
];
$thingyWithArrayAccess = $this->createMock(ThingyWithArrayAccess::class);
$thingyWithArrayAccess->method('offsetGet')
->willReturnCallback(
function ($offset) use ($theArray)
return $theArray[$offset];
);
$thingyWithArrayAccess->method('offsetExists')
->willReturnCallback(
function ($offset) use ($theArray)
return array_key_exists($offset, $theArray);
);
【讨论】:
哇,过去的大爆炸!自从我在 PHP 中工作以来,已经差不多有这么长的时间了。以上是关于模拟/存根在 PHPUnit 中实现数组访问的类的对象的主要内容,如果未能解决你的问题,请参考以下文章
在 PHPUnit 中实现给定接口的模拟对象上的未定义方法?