您如何使用phpUnit测试以下代码?
class Product {
protected $id = null;
public function __construct($id) {
$this->id = $id;
}
public function getDescription($language_id) {
$db_query = mysql_query("SELECT * FROM products_description WHERE products_id = " . (int) $this->id . " AND language = " . (int) $language_id);
return mysql_fetch_array($db_query);
}
}
$product = new Product(1);
$product->getDescription(1); // Test this
目前我的测试方式如下:
public function testShouldGetProductsDescription() {
$product = new Product(1);
$description = $product->getDescription(1);
$expected_description = array(
'name' => 'car',
'short_text' => 'this is a car',
'long_text' => 'longer description for the car'
);
$this->assertEquals($description, $expected_description);
}
但对我来说这似乎不是一个好的解决方案。 (此代码只是一个示例,可能无法正常工作)
答案 0 :(得分:2)
我之前已经编写了这样的测试代码,而且让我担心的是,如果数据库的内容发生变化,即使代码仍然正确,我的测试也会失败。
有几个解决方案:
答案 1 :(得分:2)
在简单的情况下,特别是与数据库耦合一样,我通常只使用存根对象来存根数据库调用。然后就像这样编写测试:
public function productFixture($id)
{
$constructor_arg = $id;
//Array of methods to stub out
$stubbed_method = array('getDescription');
//Create a mock for the Product class.
$product = $this->getMock('Product', $stubbed_method, $constructor_arg);
//Stub out expected results
$expected_description = array(
'name' => 'car',
'short_text' => 'this is a car',
'long_text' => 'longer description for the car'
);
//Configure the stub method and its return value
$product->expects($this->any())
->method('getDescription')
->will($this->returnValue($expected_description));
return $product;
}
public function testShouldGetProductsDescription()
{
$product = $this->productFixture(1);
$description = $product->getDescription(1);
$this->assertNotNull($description);
//You could test the description using assertEquals
//but I find just testing the field names is less brittle
$this->assertArrayHasKey('name', $description);
$this->assertArrayHasKey('short_text', $description);
$this->assertArrayHasKey('long_text', $description);
}
public function productFixture($id)
{
$constructor_arg = $id;
//Array of methods to stub out
$stubbed_method = array('getDescription');
//Create a mock for the Product class.
$product = $this->getMock('Product', $stubbed_method, $constructor_arg);
//Stub out expected results
$expected_description = array(
'name' => 'car',
'short_text' => 'this is a car',
'long_text' => 'longer description for the car'
);
//Configure the stub method and its return value
$product->expects($this->any())
->method('getDescription')
->will($this->returnValue($expected_description));
return $product;
}
public function testShouldGetProductsDescription()
{
$product = $this->productFixture(1);
$description = $product->getDescription(1);
$this->assertNotNull($description);
//You could test the description using assertEquals
//but I find just testing the field names is less brittle
$this->assertArrayHasKey('name', $description);
$this->assertArrayHasKey('short_text', $description);
$this->assertArrayHasKey('long_text', $description);
}
有关Stubs / Mocks和PHPUnit的更多信息:PHPUnit Manual: Test Doubles
答案 2 :(得分:1)
您的Product类与数据库紧密耦合,因为它直接调用mysql_query
。如果将它松散地耦合到数据库,例如使用Database对象或ProductStore对象,则可以在不实际使用数据库的情况下测试Product类。