单元测试和静态方法
阅读并学习单元测试,尝试理解下面的文章,该文章解释了静态函数调用的困难。
我不清楚这个问题。我一直认为静态函数是在类中舍入实用函数的一种好方法。例如,我经常使用静态函数调用进行初始化,即:
Init::loadConfig('settings.php');Init::setErrorHandler(APP_MODE);
Init::loggingMode(APP_MODE);
// start loading app related objects ..
$app = new App();
//阅读这篇文章后,我现在的目标是…
$init = new Init();$init->loadConfig('settings.php');
$init->loggingMode(APP_MODE);
// etc ...
但是,我为此课程编写的几十个测试是相同的。我什么都没改变,他们仍然都过去了。难道我做错了什么?
该帖子的作者指出:
静态方法的基本问题是它们是过程代码。
我不知道如何对程序代码进行单元测试。单元测试假设我可以孤立地实例化我的应用程序的一部分。在实例化过程中,我将依赖关系与模拟/友好关系连接起来,以替换实际的依赖关系。使用过程编程时,由于没有对象,因此代码和数据是分开的,因此无需“连线”。
现在,我从这篇文章中了解到静态方法会创建依赖关系,但是却无法直观地理解为什么不能像常规方法那样轻松地测试静态方法的返回值?
我将避免使用静态方法,但如果有的话,我希望有一个WHEN静态方法有用的想法。从这篇文章看来,静态方法与全局变量一样邪恶,应尽可能避免使用。
任何有关该主题的其他信息或链接将不胜感激。
回答:
静态方法本身并不比实例方法难测试。当一个方法(静态方法或其他方法)调用 其他
静态方法时会出现问题,因为您无法隔离正在测试的方法。这是一个很难测试的典型示例方法:
public function findUser($id) { Assert::validIdentifier($id);
Log::debug("Looking for user $id"); // writes to a file
Database::connect(); // needs user, password, database info and a database
return Database::query(...); // needs a user table with data
}
您可能想用这种方法测试什么?
- 传递除正整数以外的任何东西都会抛出异常
InvalidIdentifierException
。 Database::query()
接收正确的标识符。null
如果没有找到,则返回匹配的用户。
这些要求很简单,但是您还必须设置日志记录,连接到数据库,向数据库中加载数据等。Database
该类应独自负责测试其可以连接和查询。该Log
班应该记录这样做。findUser()
应该不必处理任何此类问题,但是必须这样做,因为这取决于它们。
相反,如果上述方法在Database
和Log
实例上调用了实例方法,则该测试可以传入具有特定于测试的脚本化返回值的模拟对象。
function testFindUserReturnsNullWhenNotFound() { $log = $this->getMock('Log'); // ignore all logging calls
$database = $this->getMock('Database', array('connect', 'query');
$database->expects($this->once())->method('connect');
$database->expects($this->once())->method('query')
->with('<query string>', 5)
->will($this->returnValue(null));
$dao = new UserDao($log, $database);
self::assertNull($dao->findUser(5));
}
如果findUser()
忽略调用connect()
,传递$id
(5
)的错误值或返回以外的其他值,则上述测试将失败null
。优点是不涉及任何数据库,从而使测试快速而稳健,这意味着它不会因与测试无关的原因而失败,例如网络故障或错误的样本数据。它使您可以专注于真正重要的事情:中包含的功能findUser()
。
以上是 单元测试和静态方法 的全部内容, 来源链接: utcz.com/qa/426286.html