Tôi sẽ đề nghị bạn tái cấu trúc mã của bạn một chút. Khi bạn phải bắt đầu suy nghĩ về việc sử dụng sự phản chiếu hoặc các loại công cụ khác, vì chỉ kiểm tra mã của bạn, có gì đó không ổn với mã của bạn.
Bạn đã đề cập đến các loại vấn đề khác nhau. Hãy bắt đầu với các lĩnh vực tư nhân. Trong trường hợp các trường riêng tư, tôi đã thêm một hàm tạo mới và các trường được thêm vào đó. Thay vì điều này:
public class ClassToTest {
private final String first = "first";
private final List<String> second = new ArrayList<>();
...
}
Tôi đã sử dụng cái này:
public class ClassToTest {
private final String first;
private final List<String> second;
public ClassToTest() {
this("first", new ArrayList<>());
}
public ClassToTest(final String first, final List<String> second) {
this.first = first;
this.second = second;
}
...
}
Đây sẽ không phải là một vấn đề ngay cả với một số mã kế thừa. Mã cũ sẽ sử dụng một hàm tạo trống và nếu bạn hỏi tôi, mã được cấu trúc lại sẽ trông sạch hơn và bạn sẽ có thể đưa các giá trị cần thiết vào thử nghiệm mà không bị phản xạ.
Bây giờ về phương pháp riêng tư. Theo kinh nghiệm cá nhân của tôi khi bạn phải bỏ một phương thức riêng để thử nghiệm, thì phương thức đó không có gì để làm trong lớp đó. Trong trường hợp đó, một mẫu chung sẽ là bọc nó trong một giao diện, giống như Callable
và sau đó bạn chuyển qua giao diện đó trong hàm tạo (với thủ thuật nhiều hàm tạo đó):
public ClassToTest() {
this(...);
}
public ClassToTest(final Callable<T> privateMethodLogic) {
this.privateMethodLogic = privateMethodLogic;
}
Chủ yếu là tất cả những gì tôi đã viết trông giống như một mô hình tiêm phụ thuộc. Theo kinh nghiệm cá nhân của tôi, nó thực sự hữu ích trong khi thử nghiệm và tôi nghĩ rằng loại mã này sạch hơn và sẽ dễ bảo trì hơn. Tôi cũng nói như vậy về các lớp lồng nhau. Nếu một lớp lồng nhau chứa logic nặng thì sẽ tốt hơn nếu bạn chuyển nó thành một lớp riêng và đã đưa nó vào một lớp cần nó.
Ngoài ra còn có một số mẫu thiết kế khác mà tôi đã sử dụng trong khi tái cấu trúc và duy trì mã kế thừa, nhưng tất cả phụ thuộc vào các trường hợp mã của bạn để kiểm tra. Sử dụng sự phản chiếu hầu như không phải là một vấn đề, nhưng khi bạn có một ứng dụng doanh nghiệp được kiểm tra nhiều và các thử nghiệm được chạy trước khi mọi triển khai thì mọi thứ trở nên rất chậm (điều đó thật khó chịu và tôi không thích kiểu đó).
Ngoài ra còn có tiêm setter, nhưng tôi không khuyến khích sử dụng. Tôi tốt hơn nên gắn bó với một nhà xây dựng và khởi tạo mọi thứ khi thực sự cần thiết, để lại khả năng tiêm các phụ thuộc cần thiết.