Làm cách nào để kiểm tra một hàm riêng hoặc một lớp có các phương thức riêng, các trường hoặc các lớp bên trong?


2728

Làm cách nào để kiểm tra đơn vị (sử dụng xUnit) một lớp có các phương thức riêng tư nội bộ, các trường hoặc các lớp lồng nhau? Hoặc một chức năng được đặt ở chế độ riêng tư bằng cách có liên kết nội bộ ( statictrong C / C ++) hoặc trong một không gian tên riêng ( ẩn danh )?

Có vẻ không tốt khi thay đổi công cụ sửa đổi truy cập cho một phương thức hoặc chức năng chỉ để có thể chạy thử nghiệm.


257
Cách tốt nhất để kiểm tra một phương pháp riêng là không kiểm tra trực tiếp
Surya


383
Tôi không đồng ý. Một phương pháp (công khai) dài hoặc khó hiểu phải được cấu trúc lại. Sẽ là hoàn toàn không thử nghiệm các phương pháp nhỏ (riêng tư) mà bạn nhận được thay vì chỉ áp dụng phương pháp công khai.
Michael Piefel

181
Không thử nghiệm bất kỳ phương pháp nào chỉ vì khả năng hiển thị của nó là ngu ngốc. Ngay cả kiểm thử đơn vị cũng phải là về đoạn mã nhỏ nhất và nếu bạn chỉ kiểm tra các phương thức công khai, bạn sẽ không bao giờ chắc chắn nơi xảy ra lỗi - phương thức đó hoặc một số khác.
Dainius

126
Bạn cần kiểm tra chức năng lớp chứ không phải thực hiện . Bạn muốn thử nghiệm các phương pháp riêng tư? Kiểm tra các phương pháp công cộng gọi chúng. Nếu chức năng mà lớp cung cấp được kiểm tra kỹ lưỡng, các phần bên trong của nó đã được chứng minh là chính xác và đáng tin cậy; bạn không cần phải kiểm tra các điều kiện bên trong. Các bài kiểm tra nên duy trì việc tách rời khỏi các lớp được kiểm tra.
Calimar41

Câu trả lời:


1640

Cập nhật:

Khoảng 10 năm sau đó có lẽ là cách tốt nhất để thử nghiệm một phương pháp tư nhân, hoặc bất kỳ thành viên không thể tiếp cận, là thông qua @Jailbreaktừ Manifold khuôn khổ.

@Jailbreak Foo foo = new Foo();
// Direct, *type-safe* access to *all* foo's members
foo.privateMethod(x, y, z);
foo.privateField = value;

Bằng cách này, mã của bạn vẫn an toàn và dễ đọc. Không thỏa hiệp thiết kế, không có phương pháp và trường quá mức cho mục đích thử nghiệm.

Nếu bạn có một phần của ứng dụng Java cũ và bạn không được phép thay đổi mức độ hiển thị của các phương thức của mình, cách tốt nhất để kiểm tra các phương thức riêng là sử dụng sự phản chiếu .

Trong nội bộ, chúng tôi đang sử dụng các trình trợ giúp để nhận / đặt privateprivate staticcác biến cũng như gọi privateprivate staticphương thức. Các mẫu sau sẽ cho phép bạn thực hiện khá nhiều thứ liên quan đến các phương thức và trường riêng. Tất nhiên, bạn không thể thay đổi private static finalcác biến thông qua sự phản chiếu.

Method method = TargetClass.getDeclaredMethod(methodName, argClasses);
method.setAccessible(true);
return method.invoke(targetObject, argObjects);

Và cho các lĩnh vực:

Field field = TargetClass.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object, value);

Ghi chú:
1. TargetClass.getDeclaredMethod(methodName, argClasses)cho phép bạn xem xét privatecác phương pháp. Điều tương tự áp dụng cho getDeclaredField.
2. Bắt setAccessible(true)buộc phải chơi xung quanh với tư nhân.


350
Có ích nếu bạn không biết API, nhưng nếu bạn phải thử nghiệm các phương thức riêng tư theo cách này thì có gì đó phù hợp với thiết kế của bạn. Như một poster khác nói rằng kiểm thử đơn vị nên kiểm tra hợp đồng của lớp: nếu hợp đồng quá rộng và khởi tạo quá nhiều hệ thống thì thiết kế nên được giải quyết.
andygavin

21
Rất hữu ích. Sử dụng điều này, điều quan trọng là phải nhớ rằng nó sẽ thất bại nặng nề nếu các bài kiểm tra được thực hiện sau khi obfuscation.
Rick Minerich

20
Mã ví dụ không hoạt động với tôi, nhưng điều này làm cho việc khai thác rõ ràng hơn: java2s.com/Tutorial/Java/0125__Reflection/ Kẻ
Rob

35
Tốt hơn nhiều so với việc sử dụng sự phản chiếu trực tiếp sẽ là sử dụng một số thư viện cho nó, chẳng hạn như Powermock .
Michael Piefel

25
Đây là lý do tại sao Test Driven Design rất hữu ích. Nó giúp bạn tìm ra những gì cần được phơi bày để xác nhận hành vi.
Thorbjørn Ravn Andersen

621

Cách tốt nhất để kiểm tra một phương thức riêng là thông qua một phương thức công khai khác. Nếu điều này không thể được thực hiện, thì một trong những điều kiện sau là đúng:

  1. Phương thức riêng là mã chết
  2. Có một mùi thiết kế gần lớp mà bạn đang thử nghiệm
  3. Phương pháp mà bạn đang cố kiểm tra không nên riêng tư

6
Hơn nữa, dù sao chúng tôi cũng không bao giờ đạt được mức độ bao phủ mã 100%, vậy tại sao không tập trung thời gian của bạn để kiểm tra chất lượng cho các phương pháp mà khách hàng sẽ thực sự sử dụng trực tiếp.
grinch

30
@grinch Tại chỗ. Điều duy nhất bạn có thể đạt được từ việc thử nghiệm các phương thức riêng tư là gỡ lỗi thông tin và đó là những gì trình gỡ lỗi dành cho. Nếu các bài kiểm tra của bạn về hợp đồng của lớp có bảo hiểm đầy đủ thì bạn có tất cả thông tin bạn cần. Phương pháp riêng là một chi tiết thực hiện . Nếu bạn kiểm tra chúng, bạn sẽ phải thay đổi các bài kiểm tra của mình mỗi khi việc triển khai của bạn thay đổi, ngay cả khi hợp đồng không có. Trong vòng đời đầy đủ của phần mềm, điều này có thể sẽ tốn kém hơn rất nhiều so với lợi ích mà nó mang lại.
Erik Madsen

9
@AlexWien bạn nói đúng. Bảo hiểm không phải là điều khoản đúng. Điều tôi nên nói là "nếu các bài kiểm tra của bạn về hợp đồng của lớp bao gồm tất cả các yếu tố đầu vào có ý nghĩa và tất cả các trạng thái có ý nghĩa". Điều này, bạn chỉ ra một cách đúng đắn, có thể chứng minh không thể kiểm tra thông qua giao diện công khai với mã hoặc gián tiếp khi bạn đề cập đến nó. Nếu đó là trường hợp đối với một số mã mà bạn đang kiểm tra, tôi sẽ có xu hướng nghĩ: (1) Hợp đồng quá hào phóng (ví dụ: quá nhiều tham số trong phương thức) hoặc (2) Hợp đồng quá mơ hồ (ví dụ: hành vi phương thức thay đổi rất nhiều với trạng thái lớp học). Tôi sẽ xem xét cả mùi thiết kế.
Erik Madsen

16
Hầu như tất cả các phương pháp riêng tư không nên được thử nghiệm trực tiếp (để giảm chi phí bảo trì). Ngoại lệ: Các phương pháp khoa học có thể có các dạng như f (a (b (c (x), d (y))), a (e (x, z)), b (f (x, y, z), z)) trong đó a, b, c, d, e và f là các biểu thức phức tạp khủng khiếp nhưng nếu không thì vô dụng bên ngoài công thức đơn lẻ này. Một số chức năng (nghĩ MD5) khó đảo ngược nên có thể khó (NP-Hard) để chọn các tham số sẽ bao phủ hoàn toàn không gian hành vi. Dễ dàng hơn để kiểm tra a, b, c, d, e, f một cách độc lập. Làm cho chúng công khai hoặc gói riêng tư rằng chúng có thể tái sử dụng. Giải pháp: làm cho chúng riêng tư, nhưng kiểm tra chúng.
Eponymous

4
@Eponymous Tôi hơi bị rách về cái này. Theo tôi, người theo chủ nghĩa thuần túy hướng đối tượng sẽ nói rằng bạn nên sử dụng một cách tiếp cận hướng đối tượng hơn là các phương thức riêng tư tĩnh, cho phép bạn kiểm tra thông qua các phương thức công khai. Nhưng sau đó, một lần nữa, trong một khung khoa học, chi phí bộ nhớ hoàn toàn có thể là mối quan tâm mà tôi tin rằng lập luận cho phương pháp tĩnh.
Erik Madsen

323

Khi tôi có các phương thức riêng trong một lớp đủ phức tạp đến mức tôi cảm thấy cần phải kiểm tra trực tiếp các phương thức riêng đó, đó là mùi mã: lớp của tôi quá phức tạp.

Cách tiếp cận thông thường của tôi để giải quyết các vấn đề như vậy là trêu chọc một lớp mới có chứa các bit thú vị. Thông thường, phương thức này và các trường mà nó tương tác với, và có thể một hoặc hai phương thức khác có thể được trích xuất sang một lớp mới.

Lớp mới hiển thị các phương thức này là 'công khai', vì vậy chúng có thể truy cập để kiểm tra đơn vị. Các lớp mới và cũ bây giờ đều đơn giản hơn lớp gốc, rất phù hợp với tôi (tôi cần giữ mọi thứ đơn giản, hoặc tôi bị lạc!).

Lưu ý rằng tôi không gợi ý rằng mọi người tạo lớp mà không sử dụng bộ não của họ! Vấn đề ở đây là sử dụng các lực lượng kiểm thử đơn vị để giúp bạn tìm các lớp mới tốt.


24
Câu hỏi là làm thế nào để kiểm tra phương pháp riêng tư. Bạn nói rằng bạn sẽ làm lớp mới cho điều đó (và thêm độ phức tạp hơn nhiều) và sau khi đề xuất không tạo lớp mới. Vậy làm thế nào để kiểm tra phương pháp riêng tư?
Dainius

27
@Dainius: Tôi không khuyên bạn chỉ nên tạo một lớp mới để bạn có thể kiểm tra phương thức đó. Tôi thực sự gợi ý rằng các bài kiểm tra viết có thể giúp bạn cải thiện thiết kế của mình: các thiết kế tốt rất dễ kiểm tra.
Jay Bazuzi

13
Nhưng bạn có đồng ý rằng chỉ có một bộ phận tốt để trưng bày (công khai) các phương thức cần thiết để lớp / đối tượng đó hoạt động chính xác không? tất cả những thứ khác nên riêng tư / bảo vệ. Vì vậy, trong một số phương thức riêng tư sẽ có một số logic và IMO thử nghiệm các phương pháp này sẽ chỉ cải thiện chất lượng phần mềm. Tất nhiên tôi đồng ý rằng nếu một số đoạn mã phức tạp thì nên chia thành các phương thức / lớp riêng biệt.
Dainius

6
@Danius: Thêm một lớp mới, trong hầu hết các trường hợp làm giảm sự phức tạp. Chỉ cần đo nó. Khả năng kiểm tra trong một số trường hợp chiến đấu chống lại OOD. Cách tiếp cận hiện đại là ưu tiên kiểm tra.
AlexWien

5
Đây chính xác là cách sử dụng phản hồi từ các bài kiểm tra của bạn để lái xe và cải thiện thiết kế của bạn! Nghe bài kiểm tra của bạn. nếu chúng khó viết, điều đó cho bạn biết điều gì đó quan trọng về mã của bạn!
pnschofield

289

Tôi đã sử dụng sự phản chiếu để làm điều này cho Java trong quá khứ và theo tôi đó là một sai lầm lớn.

Nói đúng ra, bạn không nên viết bài kiểm tra đơn vị trực tiếp kiểm tra các phương pháp riêng tư. Những gì bạn nên kiểm tra là hợp đồng công khai mà lớp có với các đối tượng khác; bạn không bao giờ nên trực tiếp kiểm tra nội bộ của một đối tượng. Nếu một nhà phát triển khác muốn thực hiện một thay đổi nhỏ đối với lớp, điều này không ảnh hưởng đến hợp đồng công khai của lớp, thì anh ta / cô ta phải sửa đổi thử nghiệm dựa trên phản ánh của bạn để đảm bảo rằng nó hoạt động. Nếu bạn làm điều này nhiều lần trong suốt một dự án, thì các bài kiểm tra đơn vị sẽ ngừng là một phép đo hữu ích về sức khỏe mã và bắt đầu trở thành một trở ngại cho sự phát triển và gây khó chịu cho nhóm phát triển.

Thay vào đó, những gì tôi khuyên bạn nên làm là sử dụng một công cụ bao phủ mã như Cobertura, để đảm bảo rằng các bài kiểm tra đơn vị bạn viết cung cấp mức độ bao phủ tốt của mã trong các phương thức riêng tư. Bằng cách đó, bạn gián tiếp kiểm tra những gì các phương thức riêng đang làm và duy trì mức độ nhanh nhẹn cao hơn.


76
+1 cho điều này. Theo tôi đó là câu trả lời tốt nhất cho câu hỏi. Bằng cách thử nghiệm các phương pháp riêng tư, bạn đang thử nghiệm việc thực hiện. Điều này đánh bại mục đích của kiểm thử đơn vị, đó là kiểm tra các đầu vào / đầu ra của hợp đồng của một lớp. Một thử nghiệm chỉ nên biết đủ về việc triển khai để mô phỏng các phương thức mà nó gọi dựa trên các phụ thuộc của nó. Chỉ có bấy nhiêu thôi. Nếu bạn không thể thay đổi triển khai của mình mà không phải thay đổi thử nghiệm - rất có thể chiến lược thử nghiệm của bạn kém.
Colin M

10
@Colin M Đó thực sự không phải là những gì anh ấy hỏi;) Hãy để anh ấy quyết định, bạn không biết dự án.
Aaron Marcus

2
Không thực sự đúng. Có thể mất rất nhiều nỗ lực để kiểm tra một phần nhỏ của phương thức riêng thông qua phương thức công khai sử dụng nó. Phương thức công khai có thể yêu cầu thiết lập đáng kể trước khi bạn tiếp cận đường dây gọi phương thức riêng tư của bạn
ACV

1
Tôi đồng ý. Bạn nên kiểm tra, nếu hợp đồng được thực hiện. Bạn không nên kiểm tra, làm thế nào điều này được thực hiện. Nếu liên hệ được thực hiện mà không đạt phạm vi bảo hiểm mã 100% (theo phương thức riêng tư), đó có thể là mã chết hoặc vô dụng.
wuppi

207

Từ bài viết này: Thử nghiệm các phương thức riêng tư với JUnit và SuiteRunner (Bill Venners), về cơ bản bạn có 4 tùy chọn:

  1. Đừng thử phương pháp riêng tư.
  2. Cung cấp cho các phương thức truy cập gói.
  3. Sử dụng một lớp kiểm tra lồng nhau.
  4. Sử dụng phản xạ.

@JimmyT., Phụ thuộc vào "mã sản xuất" dành cho ai. Tôi sẽ gọi mã được sản xuất cho các ứng dụng được đặt trong VPN có người dùng mục tiêu là sysadins là mã sản xuất.
Pacerier

@Pacerier Ý bạn là gì?
Jimmy T.

1
Tùy chọn thứ 5, như đã đề cập ở trên là thử nghiệm phương thức công khai gọi phương thức riêng? Chính xác?
dùng2441441

1
@LorenzoLellow Tôi đã vật lộn với điều này vì tôi đang thực hiện phát triển nhúng và tôi muốn phần mềm của mình nhỏ nhất có thể. Hạn chế kích thước và hiệu suất là lý do duy nhất tôi có thể nghĩ đến.

Tôi thực sự thích thử nghiệm bằng cách sử dụng sự phản chiếu: Ở đây mẫu Phương thức method = targetClass.getDeclaredMethod (methodName, argC Cầu); phương thức.setAccessible (đúng); return method.invoke (targetObject, argObjects);
Ác mộng

127

Nói chung, một bài kiểm tra đơn vị được dự định để thực hiện giao diện chung của một lớp hoặc đơn vị. Do đó, các phương thức riêng là chi tiết triển khai mà bạn không muốn kiểm tra một cách rõ ràng.


16
Đó là câu trả lời tốt nhất IMO, hay như người ta thường nói, kiểm tra hành vi, không phải phương pháp. Kiểm thử đơn vị không phải là sự thay thế cho các số liệu mã nguồn, các công cụ phân tích mã tĩnh và đánh giá mã. Nếu các phương thức riêng phức tạp đến mức chúng cần tách các thử nghiệm thì có lẽ nó cần phải được cấu trúc lại, không có nhiều thử nghiệm được ném vào nó.
Dan Haynes

14
Vì vậy, đừng viết phương thức riêng tư, chỉ cần tạo 10 lớp nhỏ khác?
dao cạo

1
Không, về cơ bản, điều đó có nghĩa là bạn có thể kiểm tra chức năng của các phương thức riêng tư bằng phương thức công khai gọi chúng.
Akshat Sharda

67

Chỉ cần hai ví dụ về nơi tôi muốn thử nghiệm một phương thức riêng tư:

  1. Thói quen giải mã - Tôi sẽ không muốn mọi người nhìn thấy chúng để xem chỉ vì mục đích thử nghiệm, bất kỳ ai khác cũng có thể sử dụng chúng để giải mã. Nhưng chúng là bản chất của mã, phức tạp và cần phải luôn hoạt động (ngoại lệ rõ ràng là sự phản chiếu có thể được sử dụng để xem ngay cả các phương thức riêng tư trong hầu hết các trường hợp, khiSecurityManager không được cấu hình để ngăn chặn điều này).
  2. Tạo SDK cho tiêu dùng cộng đồng. Ở đây công chúng mang một ý nghĩa hoàn toàn khác, vì đây là mã mà cả thế giới có thể thấy (không chỉ nội bộ trong ứng dụng của tôi). Tôi đặt mã vào các phương thức riêng tư nếu tôi không muốn người dùng SDK thấy nó - Tôi không thấy đây là mùi mã, chỉ đơn thuần là cách lập trình SDK hoạt động. Nhưng tất nhiên tôi vẫn cần thử nghiệm các phương thức riêng tư của mình và chúng là nơi chức năng của SDK của tôi thực sự sống.

Tôi hiểu ý tưởng chỉ thử nghiệm "hợp đồng". Nhưng tôi không thấy người ta có thể ủng hộ việc thực sự không kiểm tra mã - số dặm của bạn có thể thay đổi.

Vì vậy, sự đánh đổi của tôi liên quan đến việc làm phức tạp JUnits bằng sự phản chiếu, thay vì ảnh hưởng đến bảo mật & SDK của tôi.


5
Mặc dù bạn không bao giờ nên công khai một phương thức chỉ để kiểm tra nó, nhưng đó privatekhông phải là phương pháp duy nhất. Không có công cụ sửa đổi truy cập nào package privatevà có nghĩa là bạn có thể kiểm tra đơn vị miễn là kiểm tra đơn vị của bạn sống trong cùng một gói.
ngreen

1
Tôi đã nhận xét về câu trả lời của bạn, đặc biệt là điểm 1, không phải OP. Không cần thiết phải đặt một phương thức riêng tư chỉ vì bạn không muốn nó được công khai.
ngreen

1
@ngreen true thx - Tôi lười với từ "công khai". Tôi đã cập nhật câu trả lời để bao gồm công khai, được bảo vệ, mặc định (và để đề cập đến sự phản ánh). Điểm tôi đã cố gắng đưa ra là có lý do chính đáng để một số mã được bí mật, tuy nhiên điều đó không ngăn chúng tôi kiểm tra nó.
Richard Le Mesurier

2
Cảm ơn đã đưa ra ví dụ thực tế cho tất cả mọi người. Hầu hết các câu trả lời là tốt, nhưng theo quan điểm lý thuyết. Trong thế giới thực, chúng ta cần phải che giấu việc thực hiện khỏi hợp đồng và chúng ta vẫn cần kiểm tra nó. Đọc tất cả những điều này, tôi nghĩ có lẽ đây là một cấp độ thử nghiệm hoàn toàn mới, với một tên khác
Z. Khullah

1
Một ví dụ nữa - Trình phân tích cú pháp HTML Crawler . Phải phân tích toàn bộ trang html thành các đối tượng miền đòi hỏi rất nhiều logic nitty-gritty để xác nhận các phần nhỏ của cấu trúc. Thật hợp lý khi chia nó thành các phương thức và gọi nó từ một phương thức công khai, nhưng sẽ không có ý nghĩa gì khi tất cả các phương thức nhỏ hơn kết hợp nó thành công khai, cũng không có ý nghĩa gì khi tạo 10 lớp trên mỗi trang HTML.
Hà Lan

59

Các phương thức riêng được gọi bằng một phương thức công khai, vì vậy các đầu vào cho các phương thức công khai của bạn cũng nên kiểm tra các phương thức riêng được gọi bằng các phương thức công khai đó. Khi một phương thức công khai thất bại, thì đó có thể là một thất bại trong phương thức riêng tư.


Sự thật. Vấn đề là khi việc triển khai phức tạp hơn, giống như nếu một phương thức công khai gọi một số phương thức riêng tư. Cái nào đã thất bại? Hoặc nếu đó là một phương thức riêng phức tạp, không thể tiếp xúc hay chuyển sang một lớp mới
Z. Khullah

Bạn đã đề cập tại sao phương pháp riêng nên được thử nghiệm. Bạn nói "thế thì có thể", nên bạn không chắc. IMO, cho dù một phương pháp nên được kiểm tra là trực giao với mức truy cập của nó.
Wei Qiu

39

Một cách tiếp cận khác mà tôi đã sử dụng là thay đổi một phương thức riêng tư để đóng gói riêng tư hoặc được bảo vệ, sau đó bổ sung nó bằng @VisibleForTesting chú thích của thư viện Google Guava.

Điều này sẽ nói với bất kỳ ai sử dụng phương pháp này để thận trọng và không truy cập trực tiếp ngay cả trong một gói. Ngoài ra, một lớp kiểm tra không cần phải ở cùng một gói vật lý , nhưng trong cùng một gói theo thử nghiệm thư mục .

Ví dụ: nếu một phương thức được kiểm tra src/main/java/mypackage/MyClass.javathì cuộc gọi thử nghiệm của bạn sẽ được đặt src/test/java/mypackage/MyClassTest.java. Bằng cách đó, bạn có quyền truy cập vào phương thức kiểm tra trong lớp kiểm tra của mình.


1
Tôi đã không biết về điều này, nó can thiệp, tôi vẫn nghĩ rằng nếu bạn cần loại công việc đó, bạn có vấn đề về thiết kế.
Seb

2
Đối với tôi, điều này giống như nói thay vì đưa chìa khóa một lần cho nhân viên cứu hỏa của bạn để kiểm tra máy khoan, bạn mở khóa cửa trước bằng một dấu hiệu trên cửa - "mở khóa để kiểm tra - nếu bạn không đến công ty chúng tôi, xin vui lòng không nhập ".
Cha Jeremy Krieg

@FrJeremyKrieg - điều đó có nghĩa là gì?
MasterJoe2

1
@ MasterJoe2: mục đích của thử nghiệm lửa là để cải thiện sự an toàn của tòa nhà của bạn trước nguy cơ hỏa hoạn. Nhưng bạn phải cung cấp cho người giám sát quyền truy cập vào tòa nhà của bạn. Nếu bạn vĩnh viễn mở khóa cửa trước, bạn sẽ tăng nguy cơ truy cập trái phép và làm cho nó kém an toàn hơn . Điều tương tự cũng đúng với mẫu VisibleForTesting - bạn đang tăng nguy cơ truy cập trái phép để giảm nguy cơ "hỏa hoạn". Tốt hơn là chỉ cấp quyền truy cập một lần để thử nghiệm khi bạn cần (ví dụ: sử dụng sự phản chiếu) thay vì để nó được mở khóa vĩnh viễn (không riêng tư).
Cha Jeremy Krieg

34

Để kiểm tra mã kế thừa với các lớp lớn và kỳ quặc, thường rất hữu ích khi có thể kiểm tra một phương thức riêng tư (hoặc công khai) mà tôi đang viết ngay bây giờ .

Tôi sử dụng gói Junitx.util.PrivateAccessor cho Java. Rất nhiều lớp lót hữu ích để truy cập các phương thức riêng tư và các trường riêng.

import junitx.util.PrivateAccessor;

PrivateAccessor.setField(myObjectReference, "myCrucialButHardToReachPrivateField", myNewValue);
PrivateAccessor.invoke(myObjectReference, "privateMethodName", java.lang.Class[] parameterTypes, java.lang.Object[] args);

2
Hãy chắc chắn tải xuống toàn bộ gói JUnit-addons ( sourceforge.net/projects/junit-addons ), chứ không phải gói PrivateAccessor của Dự án được đề xuất.
skia.heliou

2
Và hãy chắc chắn rằng, khi bạn đang sử dụng Classlàm tham số đầu tiên của mình trong các phương thức này, rằng bạn chỉ truy cập staticcác thành viên.
skia.heliou

31

Trong Spring Framework, bạn có thể kiểm tra các phương thức riêng tư bằng phương thức này:

ReflectionTestUtils.invokeMethod()

Ví dụ:

ReflectionTestUtils.invokeMethod(TestClazz, "createTest", "input data");

Các giải pháp sạch nhất và ngắn gọn nhất cho đến nay, nhưng chỉ khi bạn đang sử dụng Spring.
Denis Nikolaenko

28

Đã thử giải pháp của Cem Catikkas bằng phản xạ cho Java, tôi phải nói rằng đây là một giải pháp tao nhã hơn tôi đã mô tả ở đây. Tuy nhiên, nếu bạn đang tìm kiếm một giải pháp thay thế cho việc sử dụng sự phản chiếu và có quyền truy cập vào nguồn bạn đang kiểm tra, thì đây vẫn sẽ là một lựa chọn.

Có khả năng trong việc thử nghiệm các phương thức riêng của một lớp, đặc biệt là với sự phát triển dựa trên thử nghiệm , nơi bạn muốn thiết kế các thử nghiệm nhỏ trước khi bạn viết bất kỳ mã nào.

Tạo một thử nghiệm với quyền truy cập vào các thành viên và phương thức riêng tư có thể kiểm tra các vùng mã khó nhắm mục tiêu cụ thể chỉ với quyền truy cập vào các phương thức công khai. Nếu một phương thức công khai có một số bước liên quan, nó có thể bao gồm một số phương thức riêng tư, sau đó có thể được kiểm tra riêng lẻ.

Ưu điểm:

  • Có thể kiểm tra độ chi tiết mịn hơn

Nhược điểm:

  • Mã kiểm tra phải nằm trong cùng một tệp với mã nguồn, có thể khó duy trì hơn
  • Tương tự với các tệp đầu ra. Class, chúng phải nằm trong cùng một gói như được khai báo trong mã nguồn

Tuy nhiên, nếu thử nghiệm liên tục yêu cầu phương pháp này, nó có thể là một tín hiệu cho thấy các phương thức riêng nên được trích xuất, có thể được thử nghiệm theo cách truyền thống, công khai.

Đây là một ví dụ phức tạp về cách thức này sẽ hoạt động:

// Import statements and package declarations

public class ClassToTest
{
    private int decrement(int toDecrement) {
        toDecrement--;
        return toDecrement;
    }

    // Constructor and the rest of the class

    public static class StaticInnerTest extends TestCase
    {
        public StaticInnerTest(){
            super();
        }

        public void testDecrement(){
            int number = 10;
            ClassToTest toTest= new ClassToTest();
            int decremented = toTest.decrement(number);
            assertEquals(9, decremented);
        }

        public static void main(String[] args) {
            junit.textui.TestRunner.run(StaticInnerTest.class);
        }
    }
}

Lớp bên trong sẽ được biên dịch thành ClassToTest$StaticInnerTest.

Xem thêm: Mẹo Java 106: Các lớp bên trong tĩnh để giải trí và kiếm lợi nhuận


26

Như những người khác đã nói ... không thử trực tiếp các phương pháp riêng tư. Dưới đây là một vài suy nghĩ:

  1. Giữ tất cả các phương pháp nhỏ và tập trung (dễ kiểm tra, dễ tìm thấy những gì sai)
  2. Sử dụng các công cụ bảo hiểm mã. Tôi thích Cobertura (ôi ngày hạnh phúc, có vẻ như đã có phiên bản mới!)

Chạy phạm vi bảo hiểm mã trên các bài kiểm tra đơn vị. Nếu bạn thấy rằng các phương thức không được kiểm tra đầy đủ, hãy thêm vào các bài kiểm tra để có được phạm vi bảo hiểm. Nhằm mục đích bảo hiểm mã 100%, nhưng nhận ra rằng bạn có thể sẽ không nhận được nó.


Lên cho bảo hiểm mã. Bất kể loại logic nào trong phương thức riêng tư, bạn vẫn đang gọi những logic đó thông qua một phương thức công khai. Một công cụ bao phủ mã có thể cho bạn thấy các phần được bao phủ bởi thử nghiệm, do đó bạn có thể xem liệu phương pháp riêng tư của mình có được thử nghiệm hay không.
coolcfan

Tôi đã thấy các lớp trong đó phương thức công khai duy nhất là chính [] và chúng bật lên GUI cộng với kết nối cơ sở dữ liệu và một vài máy chủ web trên toàn thế giới. Dễ dàng nói "đừng kiểm tra gián tiếp" ...
Audrius Meskauskas

26

Phương pháp riêng tư được tiêu thụ bởi những người công cộng. Nếu không, chúng là mã chết. Đó là lý do tại sao bạn thử nghiệm phương thức công khai, khẳng định kết quả mong đợi của phương thức công khai và do đó, phương pháp riêng mà nó sử dụng.

Kiểm tra các phương thức riêng tư nên được kiểm tra bằng cách gỡ lỗi trước khi chạy thử nghiệm đơn vị của bạn trên các phương thức công khai.

Chúng cũng có thể được gỡ lỗi bằng cách sử dụng phát triển dựa trên kiểm tra, gỡ lỗi kiểm tra đơn vị của bạn cho đến khi tất cả các xác nhận của bạn được đáp ứng.

Cá nhân tôi tin rằng tốt hơn là tạo các lớp bằng TDD; tạo sơ khai phương thức công khai, sau đó tạo các thử nghiệm đơn vị với tất cả các xác nhận được xác định trước, do đó, kết quả mong đợi của phương thức được xác định trước khi bạn mã hóa nó. Bằng cách này, bạn không đi sai đường dẫn đến việc xác nhận kiểm tra đơn vị phù hợp với kết quả. Lớp học của bạn sau đó mạnh mẽ và đáp ứng các yêu cầu khi tất cả các bài kiểm tra đơn vị của bạn vượt qua.


2
Mặc dù điều này là đúng, nhưng nó có thể dẫn đến một số thử nghiệm rất phức tạp - đó là một mô hình tốt hơn để thử nghiệm một phương pháp tại một thời điểm (Thử nghiệm đơn vị) thay vì toàn bộ một nhóm trong số chúng. Không phải là một gợi ý khủng khiếp nhưng tôi nghĩ có câu trả lời tốt hơn ở đây - đây nên là phương sách cuối cùng.
Bill K

24

Nếu sử dụng Spring, ReflectionTestUtils cung cấp một số công cụ hữu ích giúp đỡ ở đây với nỗ lực tối thiểu. Ví dụ: để thiết lập một bản giả trên một thành viên riêng mà không bị buộc phải thêm một trình thiết lập công khai không mong muốn:

ReflectionTestUtils.setField(theClass, "theUnsettableField", theMockObject);

24

Nếu bạn đang cố kiểm tra mã hiện tại mà bạn miễn cưỡng hoặc không thể thay đổi, thì sự phản chiếu là một lựa chọn tốt.

Nếu thiết kế của lớp vẫn linh hoạt và bạn đã có một phương thức riêng phức tạp mà bạn muốn kiểm tra riêng, tôi khuyên bạn nên rút nó ra thành một lớp riêng và kiểm tra riêng lớp đó. Điều này không phải thay đổi giao diện chung của lớp gốc; bên trong nó có thể tạo một thể hiện của lớp trình trợ giúp và gọi phương thức của trình trợ giúp.

Nếu bạn muốn kiểm tra các điều kiện lỗi khó khăn đến từ phương thức trợ giúp, bạn có thể tiến thêm một bước. Trích xuất một giao diện từ lớp trình trợ giúp, thêm một getter công khai và setter vào lớp gốc để tiêm lớp trình trợ giúp (được sử dụng thông qua giao diện của nó), sau đó đưa một phiên bản giả của lớp trình trợ giúp vào lớp ban đầu để kiểm tra cách lớp gốc đáp ứng với các ngoại lệ từ người trợ giúp. Cách tiếp cận này cũng hữu ích nếu bạn muốn kiểm tra lớp gốc mà không kiểm tra lớp người trợ giúp.


19

Kiểm tra các phương thức riêng phá vỡ sự đóng gói của lớp của bạn bởi vì mỗi khi bạn thay đổi triển khai nội bộ, bạn sẽ phá vỡ mã máy khách (trong trường hợp này là các kiểm tra).

Vì vậy, đừng thử nghiệm các phương pháp riêng tư.


4
kiểm tra đơn vị và mã src là một cặp. Nếu bạn thay đổi src, có thể bạn phải thay đổi bài kiểm tra đơn vị. Đó là ý nghĩa của bài kiểm tra Junit. Họ sẽ bỏ trốn rằng tất cả các công trình như trước đây. và nó là tốt nếu họ phá vỡ, nếu bạn thay đổi mã.
AlexWien

1
Không đồng ý rằng kiểm tra đơn vị sẽ thay đổi nếu mã thay đổi. Nếu bạn được yêu cầu thêm chức năng cho một lớp mà không thay đổi chức năng hiện có của lớp, thì các bài kiểm tra đơn vị tồn tại phải vượt qua ngay cả khi bạn đã thay đổi mã của mình. Như Peter đề cập, các bài kiểm tra đơn vị nên kiểm tra giao diện, chứ không phải cách nó được thực hiện trong nội bộ. Trong Test Driven Development, các bài kiểm tra đơn vị được tạo trước khi mã được viết, để tập trung vào giao diện của lớp, chứ không phải về cách giải quyết nội bộ.
Harald Coppoolse

16

Câu trả lời từ trang Câu hỏi thường gặp của JUnit.org :

Nhưng nếu bạn phải ...

Nếu bạn đang sử dụng JDK 1.3 trở lên, bạn có thể sử dụng sự phản chiếu để lật đổ cơ chế kiểm soát truy cập với sự trợ giúp của Đặc quyền . Để biết chi tiết về cách sử dụng nó, hãy đọc bài viết này .

Nếu bạn đang sử dụng JDK 1.6 trở lên và bạn chú thích các thử nghiệm của mình với @Test, bạn có thể sử dụng Dp4j để thực hiện phản xạ trong các phương thức thử nghiệm của mình. Để biết chi tiết về cách sử dụng nó, xem tập lệnh thử nghiệm này .

PS Tôi là người đóng góp chính cho Dp4j , hãy hỏi tôi nếu bạn cần giúp đỡ. :)


16

Nếu bạn muốn kiểm tra các phương thức riêng tư của một ứng dụng cũ, nơi bạn không thể thay đổi mã, một tùy chọn cho Java là jMockit , cho phép bạn tạo giả cho một đối tượng ngay cả khi chúng riêng tư với lớp.


4
Là một phần của thư viện jmockit, bạn có quyền truy cập vào lớp Deencapsulation, giúp kiểm tra các phương thức riêng tư dễ dàng: Deencapsulation.invoke(instance, "privateMethod", param1, param2);
Domenic D.

Tôi sử dụng phương pháp này mọi lúc. Rất hữu ích
MedicineMan

14

Tôi có xu hướng không thử nghiệm các phương pháp riêng tư. Có sự điên rồ. Cá nhân, tôi tin rằng bạn chỉ nên kiểm tra các giao diện được hiển thị công khai của mình (và bao gồm các phương thức được bảo vệ và nội bộ).


14

Nếu bạn đang sử dụng JUnit, hãy xem Junit-addons . Nó có khả năng bỏ qua mô hình bảo mật Java và truy cập các phương thức và thuộc tính riêng tư.


13

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ư Callablevà 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.


1
Không đồng ý với việc ClassToTest(Callable)tiêm. Điều đó làm cho ClassToTestphức tạp hơn. Giữ cho nó đơn giản. Ngoài ra, sau đó yêu cầu người khác nói ClassToTestmột cái gì đó ClassToTestnên là ông chủ của. Có một nơi để tiêm logic, nhưng đây không phải là nó. Bạn vừa làm cho lớp học khó hơn để duy trì, không dễ dàng hơn.
Loduwijk

Ngoài ra, tốt hơn là nếu phương pháp kiểm tra của Xbạn không tăng Xđộ phức tạp đến mức có thể gây ra nhiều vấn đề hơn ... và do đó yêu cầu thử nghiệm bổ sung ... nếu bạn thực hiện theo cách có thể gây ra nhiều vấn đề hơn .. (đây không phải là một vòng lặp vô hạn; mỗi vòng lặp có thể nhỏ hơn vòng lặp trước đó, nhưng vẫn gây khó chịu)
Loduwijk

2
Bạn có thể giải thích tại sao nó sẽ làm cho lớp học ClassToTestkhó hơn để duy trì? Trên thực tế, nó làm cho ứng dụng của bạn dễ bảo trì hơn, bạn gợi ý gì về việc tạo lớp mới cho mọi giá trị khác nhau mà bạn cần trong firstcác biến số 'thứ hai'?
GROX13

1
Phương pháp kiểm tra không làm tăng sự phức tạp. Đó chỉ là lớp học của bạn được viết kém, kém đến mức không thể kiểm tra được.
GROX13

Khó duy trì hơn vì lớp học phức tạp hơn. class A{ A(){} f(){} }đơn giản hơn class A { Logic f; A(logic_f) } class B { g() { new A( logic_f) } }. Nếu điều đó không đúng và nếu đúng thì việc cung cấp logic của lớp là các đối số của hàm tạo sẽ dễ duy trì hơn, thì chúng ta sẽ chuyển tất cả logic dưới dạng đối số của hàm tạo. Tôi chỉ không thấy làm thế nào bạn có thể yêu cầu class B{ g() { new A( you_dont_know_your_own_logic_but_I_do ) } }làm cho A dễ bảo trì hơn. Có những trường hợp tiêm như thế này có ý nghĩa, nhưng tôi không thấy ví dụ của bạn là "dễ duy trì hơn"
Loduwijk

12

Một phương thức riêng tư chỉ được truy cập trong cùng một lớp. Vì vậy, không có cách nào để kiểm tra một phương thức riêng tư của Trực tuyến của một lớp mục tiêu từ bất kỳ lớp kiểm tra nào. Một lối thoát là bạn có thể thực hiện kiểm tra đơn vị theo cách thủ công hoặc có thể thay đổi phương thức của mình từ chế độ riêng tư của người dùng thành người được bảo vệ.

Và sau đó, một phương thức được bảo vệ chỉ có thể được truy cập trong cùng một gói nơi lớp được định nghĩa. Vì vậy, kiểm tra một phương thức được bảo vệ của lớp mục tiêu có nghĩa là chúng ta cần xác định lớp kiểm tra của bạn trong cùng gói với lớp mục tiêu.

Nếu tất cả các cách trên không phù hợp với yêu cầu của bạn, hãy sử dụng cách phản ánh để truy cập phương thức riêng tư.


Bạn đang trộn "được bảo vệ" với "thân thiện". Một phương thức được bảo vệ chỉ có thể được truy cập bởi một lớp có các đối tượng được gán cho lớp đích (tức là các lớp con).
Sayo Oladeji

1
Trên thực tế không có "Thân thiện" trong Java, thuật ngữ này là "Gói" và nó được biểu thị bằng việc thiếu công cụ sửa đổi riêng tư / công khai / được bảo vệ. Tôi vừa mới sửa câu trả lời này nhưng có một câu trả lời thực sự hay đã nói điều này - vì vậy tôi chỉ khuyên bạn nên xóa nó.
Bill K

Tôi gần như thất vọng, suy nghĩ tất cả cùng "Câu trả lời này hoàn toàn sai." cho đến khi tôi đến câu cuối cùng, điều này mâu thuẫn với phần còn lại của câu trả lời. Câu cuối cùng nên là câu đầu tiên.
Loduwijk

11

Như nhiều người ở trên đã đề xuất, một cách tốt là kiểm tra chúng thông qua các giao diện công cộng của bạn.

Nếu bạn làm điều này, nên sử dụng một công cụ bao phủ mã (như Emma) để xem liệu các phương thức riêng tư của bạn có thực sự được thực hiện từ các thử nghiệm của bạn hay không.


Bạn không nên gián tiếp kiểm tra! Không chỉ chạm qua bảo hiểm; kiểm tra rằng kết quả dự kiến ​​được cung cấp!
AlexWien

11

Đây là chức năng chung của tôi để kiểm tra các trường riêng:

protected <F> F getPrivateField(String fieldName, Object obj)
    throws NoSuchFieldException, IllegalAccessException {
    Field field =
        obj.getClass().getDeclaredField(fieldName);

    field.setAccessible(true);
    return (F)field.get(obj);
}

10

Xin vui lòng xem dưới đây cho một ví dụ;

Cần thêm câu lệnh nhập sau:

import org.powermock.reflect.Whitebox;

Bây giờ bạn có thể trực tiếp truyền đối tượng có phương thức riêng, tên phương thức được gọi và các tham số bổ sung như dưới đây.

Whitebox.invokeMethod(obj, "privateMethod", "param1");

10

Hôm nay, tôi đã đẩy một thư viện Java để giúp kiểm tra các phương thức và trường riêng. Nó đã được thiết kế dành cho Android, nhưng nó thực sự có thể được sử dụng cho bất kỳ dự án Java nào.

Nếu bạn có một số mã với các phương thức riêng tư hoặc các trường hoặc hàm tạo, bạn có thể sử dụng BoundBox . Nó làm chính xác những gì bạn đang tìm kiếm. Dưới đây là một ví dụ về thử nghiệm truy cập hai trường riêng của một hoạt động Android để kiểm tra nó:

@UiThreadTest
public void testCompute() {

    // Given
    boundBoxOfMainActivity = new BoundBoxOfMainActivity(getActivity());

    // When
    boundBoxOfMainActivity.boundBox_getButtonMain().performClick();

    // Then
    assertEquals("42", boundBoxOfMainActivity.boundBox_getTextViewMain().getText());
}

BoundBox giúp dễ dàng kiểm tra các trường, phương thức và hàm tạo riêng tư / được bảo vệ. Bạn thậm chí có thể truy cập những thứ bị ẩn bởi thừa kế. Thật vậy, BoundBox phá vỡ đóng gói. Nó sẽ cung cấp cho bạn quyền truy cập vào tất cả những điều đó thông qua sự phản ánh, NHƯNG mọi thứ đều được kiểm tra tại thời điểm biên dịch.

Đó là lý tưởng để thử nghiệm một số mã kế thừa. Sử dụng cẩn thận. ;)

https://github.com/stephanenicolas/boundbox


1
Chỉ cần thử nó, BoundBox là một giải pháp đơn giản và thanh lịch!
vào

9

Đầu tiên, tôi sẽ ném câu hỏi này ra: Tại sao các thành viên tư nhân của bạn cần thử nghiệm biệt lập? Có phải chúng phức tạp, cung cấp các hành vi phức tạp như vậy để yêu cầu thử nghiệm ngoài bề mặt công cộng? Đó là thử nghiệm đơn vị, không phải thử nghiệm 'dòng mã'. Đừng đổ mồ hôi những thứ nhỏ nhặt.

Nếu chúng đủ lớn, đủ lớn để các thành viên tư nhân này có độ phức tạp lớn của một "đơn vị" - hãy xem xét tái cấu trúc các thành viên tư nhân đó ra khỏi lớp này.

Nếu tái cấu trúc là không phù hợp hoặc không khả thi, bạn có thể sử dụng mẫu chiến lược để thay thế quyền truy cập vào các hàm thành viên / lớp thành viên riêng này khi được kiểm tra đơn vị không? Trong thử nghiệm đơn vị, chiến lược sẽ cung cấp xác nhận bổ sung, nhưng trong các bản dựng phát hành, nó sẽ đơn giản vượt qua.


3
Bởi vì thường một đoạn mã cụ thể từ một phương thức công khai được tái cấu trúc thành một phương thức riêng tư nội bộ và thực sự là đoạn logic quan trọng mà bạn có thể đã sai. Bạn muốn kiểm tra điều này một cách độc lập với phương thức công khai
oxbow_lakes

Ngay cả mã ngắn nhất đôi khi không có kiểm tra đơn vị cũng không chính xác. Chỉ cần cố gắng để nhân ra sự khác biệt giữa 2 góc địa lý. 4 dòng mã và hầu hết sẽ không làm đúng ngay lần thử đầu tiên. Các phương thức như vậy cần kiểm tra đơn vị, bởi vì hình thức là cơ sở của mã tin cậy. (Mã cũng hữu ích như vậy cũng có thể được công khai; ít được bảo vệ hữu ích hơn
AlexWien

8

Gần đây tôi có vấn đề này và đã viết một công cụ nhỏ, được gọi là Picklock , để tránh các vấn đề rõ ràng khi sử dụng API phản chiếu Java, hai ví dụ:

Các phương thức gọi, ví dụ private void method(String s)- bằng phản xạ Java

Method method = targetClass.getDeclaredMethod("method", String.class);
method.setAccessible(true);
return method.invoke(targetObject, "mystring");

Phương thức gọi, ví dụ private void method(String s)- bởi Picklock

interface Accessible {
  void method(String s);
}

...
Accessible a = ObjectAccess.unlock(targetObject).features(Accessible.class);
a.method("mystring");

Đặt các trường, ví dụ private BigInteger amount;- bằng phản chiếu Java

Field field = targetClass.getDeclaredField("amount");
field.setAccessible(true);
field.set(object, BigInteger.valueOf(42));

Cài đặt các trường, ví dụ private BigInteger amount;- bởi Picklock

interface Accessible {
  void setAmount(BigInteger amount);
}

...
Accessible a = ObjectAccess.unlock(targetObject).features(Accessible.class);
a.setAmount(BigInteger.valueOf(42));

7

PowerMockito được tạo ra cho việc này. Sử dụng phụ thuộc maven

<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-mockito-release-full</artifactId>
    <version>1.6.4</version>
</dependency>

Sau đó bạn có thể làm

import org.powermock.reflect.Whitebox;
...
MyClass sut = new MyClass();
SomeType rval = Whitebox.invokeMethod(sut, "myPrivateMethod", params, moreParams);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.