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
- package com.puritys;
- public class Food {
- private String getLink(final int type) {
- switch(type) {
- case 1:
- return "http://xxx.xx.xx/xxx.html";
- case 2:
- return "/xxx.html";
- }
- return "none";
- }
- }
接著我要寫一個 Unit test , 為了測試 private method ,我們必需先用 getDeclaredMethod 拿到 Java method ,再修改它的 accessible = true,方式如下:
Test private method
- package com.puritys;
- import static org.junit.Assert.assertEquals;
- import java.lang.reflect.Method;
- import org.junit.*;
- import com.puritys.Food;
- public class FoodTest {
- private Food tester;
- @Before
- public void setUp() throws Exception {
- this.tester = new Food();
- }
- @Test
- public void testApp() throws Exception {
- Method method = this.tester.getClass().getDeclaredMethod("getLink", int.class);
- method.setAccessible(true);
- Object[] parameters = new Object[1];
- parameters[0] = 1;
- String ret = (String) method.invoke(this.tester, parameters);
- assertEquals("The url should be http://", "http://xxx.xx.xx/xxx.html", ret);
- parameters[0] = 2;
- ret = (String) method.invoke(this.tester, parameters);
- assertEquals("The url should be xx", "/xxx.html", ret);
- }
- }
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
- public class Food {
- private String name = "Apple";
- public String getName() {
- return this.name;
- }
- }
測試 private method 的方式跟測 private property 很像,我們先用 getDeclaredField 拿到 Java property ,再用 setAccessible 修改 access 權限。
test private property
- package com.puritys;
- import static org.junit.Assert.assertEquals;
- import java.lang.reflect.Field;
- import org.junit.*;
- import com.puritys.Food;
- public class FoodTest {
- @Test
- public void testGetName() {
- String name = "";
- try {
- Field f = this.tester.getClass().getDeclaredField("name");
- f.setAccessible(true);
- name = (String) f.get(this.tester);
- } catch (Exception e) {
- System.out.println("has exception, error msg = " + e.getMessage());
- }
- assertEquals("The name should be Apple", name, "Apple");
- }
- }