gpt4 book ai didi

PHPUnit 和命名空间 - 仍在调用模拟方法

转载 作者:行者123 更新时间:2023-12-04 18:06:18 27 4
gpt4 key购买 nike

我正在向使用命名空间的现有项目添加单元测试。我以前从未使用过 namespace ,所以这有点冒险。我的问题是,在我的单元测试中,模拟方法似乎仍在被调用。下面是代码文件和测试的示例。

private function selectFromDb($fields, $criteria = null) {
$fields = is_array($fields) ? implode(', ', $fields) : $fields;

$sql = "SELECT $fields FROM balloons";

if(!is_null($criteria)) {
$sql .= " WHERE $criteria";
}

$adapter = $this->getAdapter();
$statement = $adapter->query($sql);
$result = $statement->execute();

return $result;
}

测试代码如下:

// I'm passing in data here which isn't consequential for the question.
public function testSelectFromDb($fields, $criteria, $expectedSql) {
$statement = $this->getMockBuilder('Zend\Db\Adapter\Driver\Pdo\Statement')
->disableOriginalConstructor()
->setMethods(array('execute'))->getMock();
$statement->expects($this->once())
->method('execute')->will($this->returnValue('fake'));

$adapter = $this->getMockBuilder('Zend\Db\Adapter\Adapter')
->disableOriginalConstructor()
->setMethods(array('query'))->getMock();
$adapter->expects($this->once())
->method('query')->with($expectedSql)
->will($this->returnValue($statement));

$bm = $this->getMockBuilder('Application\Model\BalloonModel')
->setMethods(array('getAdapter'))
->disableOriginalConstructor()->getMock();
$bm->expects($this->once())
->method('getAdapter')->will($this->returnValue($adapter));

// I use reflection as the method is private to the class
$reflection = new ReflectionClass($bm);
$method = $reflection->getMethod('selectFromDb');
$method->setAccessible(true);

$result = $method->invokeArgs($bm, array($fields, $criteria));

}

在这一点上,我只是试图让测试执行到最后,但我继续得到以下错误:

Tests\Model\BalloonModelTest::testSelectFromDb with data set "singleField" ('id', NULL, 'SELECT id FROM balloon')
Zend\Db\Adapter\Exception\InvalidQueryException: Statement could not be executed

/apath/PHP/vendor/zendframework/zendframework/library/zend/db/adapter/driver/pdo/statement.php:245
/apath/PHP/vendor/zendframework/zendframework/library/zend/db/adapter/driver/pdo/statement.php:240
/apath/PHP/module/Application/src/application/model/balloonmodel.php:243
/apath/PHP/tests/Model/BalloonModelTest.php:70

Caused by
PDOException: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'id' in 'field list'

/apath/PHP/vendor/zendframework/zendframework/library/zend/db/adapter/driver/pdo/statement.php:240
/apath/PHP/module/Application/src/application/model/balloonmodel.php:243
/apath/PHP/tests/Model/BalloonModelTest.php:70

这告诉我 'getAdapter'、'query' 和 'execute' 调用仍在进行,即使它们在理论上都是模拟的。我已尽我所能验证所使用的类名使用的是正确的命名空间。有什么想法吗?

最佳答案

问题不在 namespace 中。可能是您尝试模拟被测类本身,我猜 getAdapter() 是一个私有(private)方法,从类中调用。

请记住,mock 是扩展原始类的生成类的对象。

现在,Mock_XYZ extends BalloonModel 添加了 mock 方法 getAdapter(),但是如果 中的 getAdapter() 方法BalloonModel 本身是私有(private)的,它不会被覆盖,但您最终会得到两种不同的方法(如果您愿意,一种是内部方法,另一种是外部方法)。

解决方案

重构您的代码以使用依赖注入(inject)。我不是在谈论 IoC 容器,只是在创建不在类本身中的其他对象,而是用 setter 或构造函数注入(inject)它们。然后您可以在创建 $adapter 模拟之后执行以下操作,而不是模拟 getAdapter():

$bm->setAdapter($adapter);

关于PHPUnit 和命名空间 - 仍在调用模拟方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25871386/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com