gpt4 book ai didi

unit-testing - Zend Framework 2 & PHPUnit - 模拟 Zend\Db\Adapter\Adapter 类

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

几年前,我在 this tutorial 之后开始学习 Zend 框架。 .在那里,它显示映射器是使用 Zend\Db\Adapter\Adapter 创建的。类来获取数据库连接,这就是我使用数据库的方式,因为没有问题。

我现在正在尝试学习如何在 Zend 应用程序上使用 PHPUnit,并且在测试映射器中的函数时遇到了困难,因为我无法模拟 Zend\Db\Adapter\Adapter。类(class)。

This tutorial Zend 网站上显示模拟数据库连接,但它使用 Zend\Db\TableGateway\TableGateway类(class)。我在网上找到的所有其他教程也使用这个类,我发现的唯一关于 Zend\Db\Adapter\Adapter 的东西类(class)是 this :

$date = new DateTime();
$mockStatement = $this->getMock('Zend\Db\Adapter\Driver\Pdo\Statement');
$mockStatement->expects($this->once())->method('execute')->with($this->equalTo(array(
'timestamp' => $date->format(FormatterInterface::DEFAULT_DATETIME_FORMAT)
)));

$mockDbDriver = $this->getMockBuilder('Zend\Db\Adapter\Driver\Pdo\Pdo')
->disableOriginalConstructor()
->getMock();

$mockDbAdapter = $this->getMock('Zend\Db\Adapter\Adapter', array(), array($mockDbDriver));
$mockDbAdapter->expects($this->once())
->method('query')
->will($this->returnValue($mockStatement));

我试过把它放到我的 setUp方法但运行 phpunit在测试类上给我以下错误:

Fatal error: Call to a member function createStatement() on null in C:\Program Files (x86)\Zend\Apache2\htdocs\test_project\vendor\zendframework\zend-db\src\Sql\Sql.php on line 128



所以我的问题是,你如何模拟 Zend\Db\Adapter\Adapter PHPUnit 中的类?

我看过 this question类似,但使用 Zend/Db/Adapter/AdapterInterface相反,我似乎无法将该代码转换为我的情况。映射器和测试类代码如下。

ProductMapper.php:
public function __construct(Adapter $dbAdapter) {
$this->dbAdapter = $dbAdapter;
$this->sql = new Sql($dbAdapter);
}

public function fetchAllProducts() {
$select = $this->sql->select('products');

$statement = $this->sql->prepareStatementForSqlObject($select);
$results = $statement->execute();

$hydrator = new ClassMethods();
$product = new ProductEntity();
$resultset = new HydratingResultSet($hydrator, $product);
$resultset->initialize($results);
$resultset->buffer();

return $resultset;
}

ProductMapperTest.php:
public function setUp() {
$date = new DateTime();

$mockStatement = $this->getMock('Zend\Db\Adapter\Driver\Pdo\Statement');
$mockStatement->expects($this->once())->method('execute')->with($this->equalTo(array(
'timestamp' => $date->format(FormatterInterface::DEFAULT_DATETIME_FORMAT)
)));

$mockDbDriver = $this->getMockBuilder('Zend\Db\Adapter\Driver\Pdo\Pdo')->disableOriginalConstructor()->getMock();

$this->mockDbAdapter = $this->getMock('Zend\Db\Adapter\Adapter', array(), array(
$mockDbDriver
));
$this->mockDbAdapter->expects($this->once())->method('query')->will($this->returnValue($mockStatement));
}

public function testFetchAllProducts() {
$resultsSet = new ResultSet();

$productMapper = new ProductMapper($this->mockDbAdapter);

$this->assertSame($resultsSet, $productMapper->fetchAllProducts());
}

编辑#1:

继威尔特的回答之后,我将映射器更改为使用 Sql构造函数中的类并将我的测试类更改为:
public function setUp() {
$mockSelect = $this->getMock('Zend\Db\Sql\Select');

$mockDbAdapter = $this->getMockBuilder('Zend\Db\Adapter\AdapterInterface')->disableOriginalConstructor()->getMock();

$this->mockStatement = $this->getMock('Zend\Db\Adapter\Driver\Pdo\Statement');

$this->mockSql = $this->getMock('Zend\Db\Sql\Sql', array('select', 'prepareStatementForSqlObject'), array($mockDbAdapter));
$this->mockSql->method('select')->will($this->returnValue($mockSelect));
$this->mockSql->method('prepareStatementForSqlObject')->will($this->returnValue($this->mockStatement));
}

public function testFetchAllProducts() {
$resultsSet = new ResultSet();

$this->mockStatement->expects($this->once())->method('execute')->with()->will($this->returnValue($resultsSet));

$productMapper = new ProductMapper($this->mockSql);

$this->assertSame($resultsSet, $productMapper->fetchAllProducts());
}

但是,我现在收到以下错误:

ProductTest\Model\ProductMapperTest::testFetchAllProducts Failed asserting that two variables reference the same object.



来自 $this->assertSame($resultsSet, $productMapper->fetchAllProducts()); 行.我是否错误地 mock 了某些东西?

编辑#2:

根据 Wilt 的建议,我将测试类更改为使用 StatementInterface改为模拟语句,因此代码现在如下所示:
public function setUp() {

$mockSelect = $this->getMock('Zend\Db\Sql\Select');

$mockDbAdapter = $this->getMockBuilder('Zend\Db\Adapter\AdapterInterface')->disableOriginalConstructor()->getMock();

$this->mockStatement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface');

$this->mockSql = $this->getMock('Zend\Db\Sql\Sql', array('select', 'prepareStatementForSqlObject'), array($mockDbAdapter));
$this->mockSql->method('select')->will($this->returnValue($mockSelect));
$this->mockSql->method('prepareStatementForSqlObject')->will($this->returnValue($this->mockStatement));

}

public function testFetchAllProducts() {
$resultsSet = new ResultSet();

$this->mockStatement->expects($this->once())->method('execute')->with()->will($this->returnValue($resultsSet));

$productMapper = new ProductMapper($this->mockSql);

$this->assertSame($resultsSet, $productMapper->fetchAllProducts());
}

但是测试用例仍然像上面那样失败。我没有更改模拟 execute 的代码行方法,因为我相信它已经返回 $resultsSet ,但是我可能是错的!

最佳答案

也许在这里更改 __construct 会更好获取 Sql 的方法实例作为参数。好像是 $dbAdapter仅在构造函数内部使用,因此在我看来,您的 ProductMapper 的实际依赖项类不是 Adapter实例,而是 Sql实例。如果您进行更改,您只需要模拟 Sql你的ProductMapperTest里面的类.

如果你不想在你的代码中做这样的改变,你仍然想继续为当前的 ProductMapper 编写测试。类,您还应该模拟 Adapter 的所有其他方法Sql 的类类在内部调用。

现在您调用$this->sql->prepareStatementForSqlObject($select);在您的 Sql 上内部调用 createStatement 的实例Adapter 的方法类(你可以看到 here on line 128 inside the Sql class )。但在你的情况下 Adapter是一个模拟,这就是引发错误的原因:

Fatal error: Call to a member function createStatement() on null in C:\Program Files (x86)\Zend\Apache2\htdocs\test_project\vendor\zendframework\zend-db\src\Sql\Sql.php on line 128



所以要解决这个问题,你应该模拟这个方法,就像你对 query 所做的一样。方法:
$mockStatement = //...your mocked statement...
$this->mockDbAdapter->expects($this->once())
->method('createStatement')
->will($this->returnValue($mockStatement));

在下一行中,您调用 $statement->execute();这意味着您还需要模拟 execute $mockStatement 中的方法.

正如你所看到的那样,这个测试变得非常麻烦。你应该问问自己,你是否走在正确的道路上并测试了正确的组件。您可以进行一些小的设计更改(改进),以便更轻松地测试您的 ProductMapper类(class)。

关于unit-testing - Zend Framework 2 & PHPUnit - 模拟 Zend\Db\Adapter\Adapter 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42133746/

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