Tôi mới dùng thử nghiệm đơn vị và PHPUnit, nhưng tôi đã đọc rất nhiều về các mẫu thiết kế và kiểm tra riêng biệt và tôi đã quyết định tái cấu trúc ứng dụng mà tôi đang làm việc để loại bỏ các lớp tĩnh, singletons, hardcoded dependencies và bất cứ điều gì khác được định nghĩa trên phạm vi toàn cầu, hy vọng làm cho nó "testable" và không phải là một nỗi đau trong ass để mantain trong tương lai, vì nó có nghĩa là một dự án dài hạn. Cho đến nay tôi tin rằng tôi hiểu lý thuyết đằng sau thử nghiệm đơn vị, nhưng tôi đã tự hỏi, trong một kịch bản mà một đại biểu xử lý các phụ thuộc lồng nhau của các đối tượng vào một Nhà máy, làm thế nào để đi thử nghiệm đơn vị cho biết dư thừa để kiểm tra nó? Và cách tiếp cận tốt nhất để kiểm tra rằng "chuỗi" phụ thuộc hoạt động tốt trong đồng bộ là gì?Thực hiện thử nghiệm đơn vị với các phụ thuộc lồng nhau và các lớp Nhà máy
Hãy để tôi minh họa các câu hỏi. Giả sử bạn có các "di sản" đoạn mã sau:
class House {
protected $material;
protected $door;
protected $knob;
public function __construct() {
$this->door = new Door();
$this->knob = $this->door->getKnob();
$this->material = "stone";
echo "House material: ".$this->material . PHP_EOL . "<br/>";
echo "Door material: ".$this->door->getMaterial() . PHP_EOL . "<br/>";
echo "Knob material: ".$this->knob->getMaterial() . PHP_EOL . "<br/>";
}
}
class Door {
protected $material;
protected $knob;
public function __construct() {
$this->knob = new Knob();
$this->material = "wood";
}
public function getKnob() {
return $this->knob;
}
public function getMaterial() {
return $this->material;
}
}
class Knob {
protected $material;
public function __construct() {
$this->material = "metal";
}
public function getMaterial() {
return $this->material;
}
}
$house = new House();
Đây là (theo như hiểu biết của tôi đi) xấu cho kiểm tra đơn vị, vì vậy chúng tôi thay thế các phụ thuộc hardcoded với DI + một lớp Factory:
class House {
protected $material;
protected $door;
protected $knob;
public function __construct($door) {
$this->door = $door;
$this->knob = $this->door->getKnob();
$this->material = "stone";
echo "House material: ".$this->material . PHP_EOL . "<br/>";
echo "Door material: ".$this->door->getMaterial() . PHP_EOL . "<br/>";
echo "Knob material: ".$this->knob->getMaterial() . PHP_EOL . "<br/>";
}
}
class Door {
protected $material;
protected $knob;
public function __construct($knob) {
$this->knob = $knob;
$this->material = "wood";
}
public function getKnob() {
return $this->knob;
}
public function getMaterial() {
return $this->material;
}
}
class Knob {
protected $material;
public function __construct() {
$this->material = "metal";
}
public function getMaterial() {
return $this->material;
}
}
class HouseFactory {
public function create() {
$knob = new Knob();
$door = new Door($knob);
$house = new House($door);
return $house;
}
}
$houseFactory = new HouseFactory();
$house = $houseFactory->create();
Bây giờ (và một lần nữa, theo như tôi hiểu) Nhà, Cửa và Núm có thể được kiểm tra đơn vị với phụ thuộc giả lập tốt. Nhưng:
1) Điều gì sẽ xảy ra với HouseFactory ngay bây giờ?
nên một chỉ:
- Không kiểm tra nó vì nó không có bất kỳ logic ứng dụng giá trị thử nghiệm chưa và nhà máy thường ở lại như vậy. Giả sử rằng nếu kiểm tra độc lập cho Nhà, Cửa & Vượt qua Nhà máy sẽ ổn.
- Tái cấu trúc nhà máy bằng cách nào đó, tức là sử dụng các hàm trong lớp để lấy từng cá thể theo cách sao cho có thể ghi đè các hàm này thông qua PHPUnit để trả về đối tượng giả, chỉ trong trường hợp có thêm một số logic trong lớp có thể sử dụng một số thử nghiệm trong tương lai.
2) Có khả thi để thiết lập các thử nghiệm dựa trên một số phụ thuộc (không được giả lập) cùng một lúc không? Tôi hiểu điều này về mặt kỹ thuật không phải là thử nghiệm đơn vị (thử nghiệm tích hợp có lẽ?) Nhưng tôi đoán nó vẫn hoàn toàn có thể thực hiện được bằng cách sử dụng PHPUnit? Với ví dụ trên, tôi muốn có thể thiết lập một bài kiểm tra không chỉ kiểm tra House, Door, Knob và HouseFactory trong sự cô lập, mà còn là kết quả của sự tương tác của các đối tượng thực với nhau, có lẽ với một số các chức năng được mô phỏng, chẳng hạn như các chức năng xử lý dữ liệu. PHPUnit có phải là lựa chọn tồi cho loại thử nghiệm này không?
Cảm ơn trước về thời gian của bạn. Tôi nhận ra một số giả định tôi đang làm có thể không chính xác, vì tôi rõ ràng không phải là một chuyên gia về vấn đề này; sửa đổi được hoan nghênh và đánh giá cao.
Nhà máy không giống như từ khóa 'mới'. Nó có thể được kiểm tra. 'HouseFactory :: create' nên làm gì? Nó tạo và * trả về * một 'House'. Bạn có thể và nên kiểm tra điều đó, hoặc với một bài kiểm tra đơn vị hoặc xác nhận với ít nhất. Ví dụ OP là đơn giản, nhưng nếu phương pháp của bạn có bất kỳ logic nào trong nó, nó sẽ được kiểm tra. – netcoder
Ngoài ra, bạn không thể kiểm tra từ khóa 'mới' trong PHP (vì nó không phải là quá tải), nhưng bạn có thể quá tải nó trong C++ cho mỗi ví dụ, và bạn nên kiểm tra nó nếu bạn làm. – netcoder
Vì hàm tạo của 'ngôi nhà' đã được kiểm tra đơn vị (theo TDD), không cần phải kiểm tra phương pháp nhà máy một cách bình thường. Bạn có thể kiểm tra tất cả mọi thứ, câu hỏi là nếu nó có ý nghĩa và thực sự là cần thiết. Kiểm tra tích hợp có thể bao gồm việc sử dụng của nhà máy và do đó bảo lãnh nếu nhà máy không phải là những gì nó đã được thực hiện cho. – hakre