静态方法本身并不比实例方法难测试。 当一个方法(静态方法或其他方法)调用其他静态方法时会出现问题,因为您无法隔离正在测试的方法。 这是一个很难测试的典型示例方法:
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
}
您可能想用这种方法测试什么?
传递除正整数以外的任何值都会抛出findUser()。
findUser()接收到正确的标识符。
找到时返回匹配的用户,否则返回findUser()。
这些要求很简单,但是您还必须设置日志记录,连接到数据库,向其加载数据等。findUser()类应独自负责测试其是否可以连接和查询。 connect()类应该对日志记录执行相同的操作。 $id不必处理这些问题,但是必须这样做,因为这取决于它们。
如果相反,上述方法调用了findUser()和2993020291762357357实例上的实例方法,则该测试可以传入具有特定于测试的脚本返回值的模拟对象。
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('', 5)
->will($this->returnValue(null));
$dao = new UserDao($log, $database);
self::assertNull($dao->findUser(5));
}
如果findUser()忽略了呼叫2993020291762357357,传递了错误的$id(上面的5)值或返回了除null以外的任何值,则上述测试将失败。其优点在于,不涉及任何数据库,因此该测试快速而健壮,这意味着它不会成功。 不能由于与测试无关的原因而失败,例如网络故障或错误的样本数据。 它使您可以专注于真正重要的事情:findUser()中包含的功能。