Gần đây tôi đã TDDing một phương pháp nhà máy. Phương pháp là tạo ra một vật thể đơn giản hoặc một vật thể được bọc trong một vật trang trí. Đối tượng được trang trí có thể là một trong một số loại tất cả mở rộng StrategClass.
Trong thử nghiệm của tôi, tôi muốn kiểm tra, nếu lớp của đối tượng được trả lại như mong đợi. Điều đó thật dễ dàng khi os đối tượng đơn giản trở lại, nhưng phải làm gì khi nó được bọc trong một vật trang trí?
Tôi viết mã bằng PHP để tôi có thể sử dụng ext/Reflection
để tìm ra một lớp đối tượng được bao bọc, nhưng dường như tôi đang quá phức tạp mọi thứ và phần nào lại lặp lại các quy tắc của TDD.
Thay vào đó, tôi quyết định giới thiệu getClassName()
rằng sẽ trả về tên lớp của đối tượng khi được gọi từ StrategClass. Tuy nhiên, khi được gọi từ trình trang trí, nó sẽ trả về giá trị được trả về bởi cùng một phương thức trong đối tượng được trang trí.
Một số mã để làm cho nó rõ ràng hơn:
interface StrategyInterface {
public function getClassName();
}
abstract class StrategyClass implements StrategyInterface {
public function getClassName() {
return \get_class($this);
}
}
abstract class StrategyDecorator implements StrategyInterface {
private $decorated;
public function __construct(StrategyClass $decorated) {
$this->decorated = $decorated;
}
public function getClassName() {
return $this->decorated->getClassName();
}
}
Và một bài kiểm tra PHPUnit
/**
* @dataProvider providerForTestGetStrategy
* @param array $arguments
* @param string $expected
*/
public function testGetStrategy($arguments, $expected) {
$this->assertEquals(
__NAMESPACE__.'\\'.$expected,
$this->object->getStrategy($arguments)->getClassName()
)
}
//below there's another test to check if proper decorator is being used
Quan điểm của tôi ở đây là: có ổn không khi giới thiệu các phương pháp như vậy, không có cách sử dụng nào khác ngoài việc làm cho các bài kiểm tra đơn vị dễ dàng hơn? Bằng cách nào đó nó không cảm thấy đúng với tôi.