Phương châm của tôi cho Java là "chỉ vì Java có các khối tĩnh, điều đó không có nghĩa là bạn nên sử dụng chúng." Truyện cười sang một bên, có rất nhiều thủ thuật trong Java mà làm cho thử nghiệm một cơn ác mộng. Hai trong số những thứ tôi ghét nhất là Lớp ẩn danh và Khối tĩnh. Chúng tôi có rất nhiều mã di sản sử dụng các khối tĩnh và đây là một trong những điểm gây phiền nhiễu trong việc đẩy các bài kiểm tra viết đơn vị của chúng tôi. Mục tiêu của chúng tôi là có thể viết các bài kiểm tra đơn vị cho các lớp phụ thuộc vào việc khởi tạo tĩnh này với các thay đổi mã tối thiểu.Chế nhạo các khối tĩnh trong Java
Cho đến nay đề xuất của tôi cho đồng nghiệp của tôi là di chuyển phần thân của khối tĩnh vào một phương pháp tĩnh riêng và gọi nó là staticInit
. Phương thức này có thể được gọi từ bên trong khối tĩnh. Đối với bài kiểm tra đơn vị, một lớp khác phụ thuộc vào lớp này có thể dễ dàng giả lập staticInit
với JMockit để không làm bất cứ điều gì. Hãy xem ví dụ này.
public class ClassWithStaticInit {
static {
System.out.println("static initializer.");
}
}
sẽ được thay đổi để
public class ClassWithStaticInit {
static {
staticInit();
}
private static void staticInit() {
System.out.println("static initialized.");
}
}
Vì vậy mà chúng ta có thể làm như sau trong một JUnit.
public class DependentClassTest {
public static class MockClassWithStaticInit {
public static void staticInit() {
}
}
@BeforeClass
public static void setUpBeforeClass() {
Mockit.redefineMethods(ClassWithStaticInit.class, MockClassWithStaticInit.class);
}
}
Tuy nhiên giải pháp này cũng đi kèm với các vấn đề của riêng nó. Bạn không thể chạy DependentClassTest
và ClassWithStaticInitTest
trên cùng một JVM vì bạn thực sự muốn khối tĩnh chạy cho ClassWithStaticInitTest
.
Bạn sẽ làm gì để hoàn thành nhiệm vụ này? Hoặc bất kỳ giải pháp nào tốt hơn, không dựa trên JMockit mà bạn cho rằng sẽ hoạt động hiệu quả hơn?
Bạn không thể giả lập phương thức 'static' hoặc' private' bằng EasyMock. Di chuyển cơ thể của bộ khởi tạo tĩnh là như xa của một refactoring chúng tôi có thể làm cho bây giờ. –
Nếu lớp được kiểm tra có phương thức init/private tĩnh, bạn muốn nó được gọi. Không vấn đề gì. Nhưng nếu đó là lớp được chế nhạo, không có vấn đề gì cho việc giả lập dễ dàng: nó sẽ không được gọi vì không có THỰC HIỆN. Bạn có thể giả lập một cách an toàn các giao diện công khai như thể các công cụ riêng tư không tồn tại. –