2015-05-13 142 views
1

如何測試私有方法,該私有方法位於私有靜態類中。如何測試私有靜態類的私有方法

public class ProjectModel { 
      //some code 
     private static class MyStaticClass{ 
      private model (Object obj, Map<String , Object> model) 
      } 
} 

我想知道,它給NoSuchMethodException

Method method = projectModel.getClass().getDeclaredMethod("model", methodParameters); 
+4

首先你應該問自己:我真的需要爲私有方法編寫單元測試嗎?如果你想測試它們,你不應該直接測試它們,而應該通過使用它們的公共方法來測試它們。 – Stultuske

+0

有兩件事:1:這不會編譯,因爲'model()'沒有返回類型。 2:私有方法不需要測試。相反,你應該確保使用這個非私有方法返回正確的結果。 – Dragondraikk

+0

您正在從外部類獲取聲明的方法。 – Mena

回答

2

假設你ProjectModel類是在包privateaccessor.tst並且您的非靜態方法model返回int

package privateaccessor.tst; 
public class ProjectModel { 
    //some code 
    private static class MyStaticClass{ 
    private int model (Object obj, Map<String , Object> model) { 
     return 42; 
    } 
    } 
} 

然後在您的測試,你可以使用反射來獲取私有類Class對象,並創建一個實例。然後您可以使用PrivateAccessor(包含在Junit Addons中)調用方法model()

@Test 
public void testPrivate() throws Throwable { 
    final Class clazz = Class.forName("privateaccessor.tst.ProjectModel$MyStaticClass"); 
    // Get the private constructor ... 
    final Constructor constructor = clazz.getDeclaredConstructor(); 
    // ... and make it accessible. 
    constructor.setAccessible(true); 
    // Then create an instance of class MyStaticClass. 
    final Object instance = constructor.newInstance(); 
    // Invoke method model(). The primitive int return value will be 
    // wrapped in an Integer. 
    final Integer result = (Integer) PrivateAccessor.invoke(instance, "model", new Class[]{Object.class, Map.class}, new Object[]{null, null}); 
    assertEquals(42, result.intValue()); 
} 
0

在私有方法和類的常規測試,不建議。如果你仍然想測試一些非公開的功能,我會建議你製作這樣的方法和類,而不是private,但是package private並且把你的測試用例放在同一個包中(但是像在Maven項目中通常做的那樣,放到單獨的源目錄中) 。

您的具體反映問題可以通過

Class.forName(ProjectModel.class.getName()+"$MyStaticClass") 
    .getDeclaredMethod("model", methodParameters); 

得到解決,但我不建議使用這種方法,因爲這將是很難支持這些測試用例的未來。

1

你可以試試這個代碼解決異常:

Method method = projectModel.getClass().getDeclaredClasses()[0] 
    .getDeclaredMethod("model", methodParameters); 

出於測試目的,你可以試試下面的代碼來調用model方法:

Class<?> innerClass = projectModel.getClass().getDeclaredClasses()[0]; 

Constructor<?> constructor = innerClass.getDeclaredConstructors()[0]; 
constructor.setAccessible(true); 

Object mystaticClass = constructor.newInstance(); 
Method method = mystaticClass.getClass().getDeclaredMethod("model", new Class[]{Object.class,Map.class}); 

method.setAccessible(true); 
method.invoke(mystaticClass, null, null);