Disclaimer: Sau rất nhiều săn bắn xung quanh trên chủ đề khác nhau tôi đã tìm thấy một câu trả lời. Nó có thể được thực hiện, nhưng sự đồng chung là nó không phải là rất an toàn nhưng nhìn thấy như thế nào bạn đang làm điều này ONLY IN kiểm tra đơn vị, tôi nghĩ rằng bạn chấp nhận những rủi ro :)
Câu trả lời là không Mocking, vì hầu hết Mocking không cho phép bạn đột nhập vào trận chung kết. Câu trả lời là một chút "hacky", nơi bạn đang thực sự sửa đổi các lĩnh vực tư nhân khi Java được gọi là lõi java.lang.reflect.Field
và java.lang.reflect.Modifier
lớp học (phản ánh). Nhìn vào this answer Tôi đã có thể ghép lại phần còn lại của bài kiểm tra của bạn mà không cần chế giễu giải quyết vấn đề của bạn.
Vấn đề với câu trả lời đó là tôi đã chạy vào NoSuchFieldException
khi cố gắng sửa đổi variable
. Trợ giúp cho việc đó nằm trong another post về cách truy cập một trường riêng tư và không công khai.
Reflection/Dòng Manipulation Giải thích:
Kể từ Mocking không thể xử lý cuối cùng, thay vì những gì chúng ta cuối cùng làm là hack vào thư mục gốc của lĩnh vực riêng của mình. Khi chúng ta sử dụng các thao tác Field
(phản chiếu), chúng ta đang tìm biến cụ thể bên trong một lớp/đối tượng. Một khi Java tìm thấy nó, chúng ta có được "modifier" của nó, cho biết biến giới hạn/quy tắc nó có như là final
, static
, private
, public
, v.v. Chúng tôi tìm biến đúng, và sau đó cho biết mã có thể truy cập cho phép chúng tôi thay đổi các công cụ sửa đổi này. Khi chúng tôi đã thay đổi "quyền truy cập" ở gốc để cho phép chúng tôi thao tác, chúng tôi sẽ chuyển sang phần "cuối cùng" của nó. Sau đó chúng ta có thể thay đổi giá trị và đặt nó thành bất cứ thứ gì chúng ta cần. Để đơn giản, chúng tôi đang sửa đổi biến để cho phép chúng tôi thay đổi các thuộc tính của nó, loại bỏ nguyên mẫu cho final
và sau đó thay đổi giá trị vì nó không còn là final
nữa. Để biết thêm thông tin về điều này, check out the post where the idea came from.
Vì vậy, từng bước chúng tôi vượt qua trong biến chúng ta muốn thao tác và ...
// Mark the field as public so we can toy with it
field.setAccessible(true);
// Get the Modifiers for the Fields
Field modifiersField = Field.class.getDeclaredField("modifiers");
// Allow us to change the modifiers
modifiersField.setAccessible(true);
// Remove final modifier from field by blanking out the bit that says "FINAL" in the Modifiers
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
// Set new value
field.set(null, newValue);
Kết hợp này tất cả vào một ĐÁP SUPER mới bạn nhận được.
@RunWith(PowerMockRunner.class)
@PrepareForTest()
class PrivateStaticFinalTest {
@Test
public void testMethod(){
try {
setFinalStatic(PrivateStaticFinal.class.getDeclaredField("variable"), Integer.valueOf(100));
}
catch (SecurityException e) {fail();}
catch (NoSuchFieldException e) {fail();}
catch (Exception e) {fail();}
assertEquals(PrivateStaticFinal.method(), Integer.valueOf(101));
}
static void setFinalStatic(Field field, Object newValue) throws Exception {
field.setAccessible(true);
// remove final modifier from field
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, newValue);
}
}
Cập nhật Các giải pháp trên sẽ làm việc chỉ dành cho những hằng số đó được khởi tạo trong tĩnh block.When tuyên bố và khởi tạo hằng số cùng một lúc, nó có thể xảy ra rằng inlines biên dịch nó, lúc này bất kỳ thay đổi nào đối với giá trị ban đầu đều bị bỏ qua.
Các thống kê này đều nằm trong cùng một lớp khiến cho việc này trở nên phức tạp. Tất cả các vấn đề tôi gặp phải là sử dụng các số liệu thống kê từ những nơi khác khi cố gắng kiểm tra một lớp học. Có để giả một phần các phần của lớp bạn đang cố gắng để thử nghiệm chỉ có vẻ xấu. Bạn không bao giờ nên chế giễu lớp bạn đang thử nghiệm, chỉ là những thứ mà nó phụ thuộc vào. – Walls