静态方法本身比实例方法更难测试。当一个方法 – 静态或其他 – 调用其他静态方法,因为你不能隔离被测试的方法时,麻烦出现。这里是一个很难测试的典型示例方法:
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。
这些要求很简单,但您还必须设置日志记录,连接到数据库,加载数据等。数据库类应该负责测试它可以连接和查询。 Log类应该对记录执行相同操作。 findUser()不应该处理任何这一点,但它必须,因为它取决于他们。
如果相反,上面的方法调用了数据库和日志实例上的实例方法,测试可以传递具有特定于手头测试的脚本返回值的mock对象。
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()忽略调用connect(),传递$ id(5以上)的错误值,或返回除null以外的任何值,上述测试将失败。其优点是没有涉及数据库,使测试快速和健壮,这意味着它不会由于与测试无关的网络故障或错误的样本数据失败。它允许您专注于真正重要的:findUser()中包含的功能。