如何使用PHPUnit模拟和测试实例化对象的函数?
问题描述:
我想写一个函数,其目的是测试数据库连接。它所做的是实例化Database
对象,尝试连接到数据库并返回结果。如何使用PHPUnit模拟和测试实例化对象的函数?
的伪代码看起来像这样
<?php
function testDatabaseLogin() {
// Get the database connection information from a file
// ...
// Database is a class which stores the connection information passed,
// When its connect() method is invoked, it tries to connect. nothing fancy
$conn = new Database($host, $port, $username, $password);
return $conn->connect(); // TRUE on success, FALSE otherwise
}
?>
此代码段是我的情况的简化版本,但应该足以说明我的问题。
我想知道我在本例中如何使用PHPUnit来模拟Database
类。我要的是我可以
- 断言,当此函数实例
Database
是正确的 - 存根的
Database
控制connect()
的参数,以返回TRUE
或FALSE
,所以我并不需要真正尝试连接到一个真实的数据库
我搜索了四周,但我发现它似乎像PHPUnit Mock对象不以这种方式工作。任何帮助表示感谢。在底线,如果它有助于简化测试,则更改函数实现是可以接受的。
谢谢。
答
有是我有时使用
<?php
class MyClass
{
public function databaseLogin() {
$conn = $this->createDatabase();
return $conn->connect(); // TRUE on success, FALSE otherwise
}
protected function createDatabase() {
new Database($host, $port, $username, $password);
}
}
然后,创建一个 “类下的测试”,扩展你的类一招:
class MyClassUnderTest extends MyClass
{
public function __construct($databaseMock)
{
$this->databaseMock = $databaseMock;
parent::__construct();
}
}
,然后在测试:
class MySuperTest
{
public function testSomethingWitDatabase()
{
$databaseMock = $this->getMockBuilder(DataBase::class)
->disableOriginalConstructor()
->getMock();
$classUnderTest = new MyClassUnderTest($databaseMock);
$this->assertTrue($classunderTest->databaseLogin());
}
}
因此,您正在将您的Database对象实例化为一个方法,该方法被刚创建用于测试的类覆盖。
+0
无论如何,最好使用依赖注入来获取更多可测试的代码...... –
不知道这是否有帮助,但我问了一个涉及嘲讽PDO连接的问题(https://stackoverflow.com/questions/46379109/testing-coverage-with-phpunit-and-pdo)。您可能需要验证参数的合理值,因为没有连接就无法检查它们实际上是否有效。 –
@NigelRen感谢您的帮助。我认为我的情况与你的不同,因为你的'DBAccess'类接受'PDO'对象。所以你可以使用PHPUnit来模拟'PDO'对象并传递它。但在我的情况下,'数据库'对象是在函数内部实例化的,这意味着即使我有一个模拟对象,我也没有办法将它传递给它。所以我在想,如果PHPUnit不能处理这种情况,我应该尝试重构函数以使其可测试。 – user7509214
我认为一般的共识是能够注入任何依赖以启用测试等,https://stackoverflow.com/questions/130794/what-is-dependency-injection提供了更多的细节。 –