2017
Mar
06

我們要使用 reflect 來測試 Java 的 private method 跟 private variable。

並且用到兩個 package: java.lang.reflect.Field 跟 java.lang.reflect.Method。

Private method

下面是一個簡單的範例, Class Food 有個 private Method 叫 getLink。

library has private method
  1. package com.puritys;
  2.  
  3. public class Food {
  4.  
  5. private String getLink(final int type) {
  6. switch(type) {
  7. case 1:
  8. return "http://xxx.xx.xx/xxx.html";
  9. case 2:
  10. return "/xxx.html";
  11. }
  12. return "none";
  13. }
  14. }

接著我要寫一個 Unit test , 為了測試 private method ,我們必需先用 getDeclaredMethod 拿到 Java method ,再修改它的 accessible = true,方式如下:

Test private method
  1. package com.puritys;
  2.  
  3. import static org.junit.Assert.assertEquals;
  4. import java.lang.reflect.Method;
  5. import org.junit.*;
  6. import com.puritys.Food;
  7.  
  8. public class FoodTest {
  9. private Food tester;
  10.  
  11. @Before
  12. public void setUp() throws Exception {
  13. this.tester = new Food();
  14. }
  15.  
  16.  
  17. @Test
  18. public void testApp() throws Exception {
  19. Method method = this.tester.getClass().getDeclaredMethod("getLink", int.class);
  20. method.setAccessible(true);
  21. Object[] parameters = new Object[1];
  22. parameters[0] = 1;
  23. String ret = (String) method.invoke(this.tester, parameters);
  24. assertEquals("The url should be http://", "http://xxx.xx.xx/xxx.html", ret);
  25.  
  26. parameters[0] = 2;
  27. ret = (String) method.invoke(this.tester, parameters);
  28. assertEquals("The url should be xx", "/xxx.html", ret);
  29.  
  30. }
  31. }
getDeclaredMethod("getLink", int.class)
  • 第二個參數是指 getLink 接受的參數型態 ,getLink 有幾個參數,這裡就要寫多少個。
m.setAccessible(true);
  • 將 private method 改成 accessible。
Object[] parameters = new Object[1];
parameters[0] = 2;
  • 不管 method 需要傳幾個參數,我們只要宣告一個 Array Object ,set 所有的參數進 Object[]

Private property

下面是一個簡單的範例, Class Food 有個 private Property 叫 name 。

private property
  1. public class Food {
  2. private String name = "Apple";
  3.  
  4. public String getName() {
  5. return this.name;
  6. }
  7.  
  8. }

測試 private method 的方式跟測 private property 很像,我們先用 getDeclaredField 拿到 Java property ,再用 setAccessible 修改 access 權限。

test private property
  1. package com.puritys;
  2. import static org.junit.Assert.assertEquals;
  3. import java.lang.reflect.Field;
  4. import org.junit.*;
  5. import com.puritys.Food;
  6. public class FoodTest {
  7. @Test
  8. public void testGetName() {
  9. String name = "";
  10. try {
  11. Field f = this.tester.getClass().getDeclaredField("name");
  12. f.setAccessible(true);
  13. name = (String) f.get(this.tester);
  14. } catch (Exception e) {
  15. System.out.println("has exception, error msg = " + e.getMessage());
  16. }
  17. assertEquals("The name should be Apple", name, "Apple");
  18. }
  19. }

回應 (Leave a comment)