2013-08-22 2 views
1

Ive는 Powermock과 Mockito를 사용하여 많은 기사를 읽었으며 다양한 방법으로 시도했지만 여전히 정적 메소드의 단위 테스트 방법을 찾아 낼 수 없습니다.리소스 번들을 사용하는 유닛 테스트 정적 메소드

public static Map<String, String> getEntries() { 
    Map<String, String> myEntriesMap = new TreeMap<String, String>(); 
    ResourceBundle myEntries = ResourceBundle.getBundle(ENTRIES_BUNDLE); 
    Enumeration<String> enumList = myEntries.getKeys(); 
    String key = null; 
    String value = null; 
    while (enumList.hasMoreElements()) { 
     key = enumList.nextElement().toString(); 
     value = myEntries.getString(key); 
     myEntriesMap.put(key, value); 
    } 
    return myEntriesMap; 
} 

코드는 이와 같이 약 30 개의 정적 메서드가 포함 된 레거시 클래스의 일부이며 리팩토링은 실제로 옵션이 아닙니다. 다른 정적 메소드에서와 마찬가지로 DB 연결도 검색 중입니다.

예 : 리소스 번들 ENTRIES_BUNDLE을 (를) 조롱하고 단위 테스트에서이 방법을 테스트하려면 어떻게해야합니까? 일반적으로 모든 정적 메서드에 적용 할 수있는 패턴을 찾고 있습니다.

+1

예,이 방법은 실제로 현재 형태로 단위 테스트 할 수 없습니다. 그것은 정적이기 때문에가 아니라'ResourceBundle.getBundle'을 호출하기 때문입니다. 이론 상으로는 리팩토링이 훨씬 더 나은 선택이 될지라도, 정말로해야한다면 PowerMock으로 할 수 있습니다. 하지만 당신의 질문을보고 나는 당신이 왜 레거시 수업을 테스트하고 있는지 궁금합니다. 확실하게, 그것이 레거시 클래스라면, 단위 테스팅의 이점을 얻는 대부분의 기회는 이미 지나갔습니다. 그리고 만약 당신이 그것을 변경할 수 없다면, 당신의 테스트가 버그를 발견한다면 당신은 무엇을 할 것입니까? –

+0

답변 해 주셔서 감사합니다. 나는 Junits를 작성함으로써 파생 된 가치에 관해 당신에게 완전히 동의합니다. 우리는이 프로젝트를 가지고 있으며 코드의 일부는 JUnits에 의해 다루어지고 코드의 일부는 그렇지 않습니다.이 아이디어는 Junits와 함께 최신 코드 전체를 가져오고 단위 테스트 케이스로 새로운 개발을 커버하는 것입니다. 레거시이며 테스트되고 안정된 코드는 (적어도 시점에서는) 리팩토링하고 싶지 않습니다. 그러나 당신이 Powermock로 이것을하는 방법을 향해 나를 가리킬 수 있다면, 그것을 말하고, 당신의 의견을보고, 그것은 매우 도움이 될 것입니다. – user2706486

+0

저는 이것을 위해 모의하려고합니다 -하지만 https://code.google.com/p/powermock/wiki/MockitoUsage13에는 정적 메소드를 모방하는 방법에 대한 정보가 있습니다. 한 화면 아래 위로. 그러나 솔직히, 가능한 경우 로지 리오의 길을 먼저 시도하십시오. –

답변

0

하면 다음과 같은 라이브러리를 사용하는 경우

하자 당신이 테스트에 xxxx.class

@MockClass(realClass = xxxx.class) 
public static class MyClass { 
    @Mock 
    public static void yyyy(){ 
      ...... 
    } 
} 

에서 메소드 YYYY를 조롱하고 싶은 말 : mockito 모두와 jmockit이 단계를 수행 :

@Test 
public void test() { 
    Mockit.setUpMock(MyClass.class); 
} 
+0

좋은 답변을 얻으려면 사용중인 조롱 프레임 워크를 설명해야합니다. OP는 Mockito와 PowerMock에 대해 물었습니다. 이 테스트를 수행하기 위해 빌드에 무엇을 추가해야합니까? –

+0

mockito-all 및 jmockit 라이브러리를 사용 중입니다. – cristi

3

ResourceBundle.getBundle 방법을 조롱 할 필요가 없습니다. 단순히 ".properties"파일을 테스트 소스 트리의 적절한 위치에 작성하십시오. 이것은 여전히 ​​완벽하게 유용하고 유용한 단위 테스트 일 것입니다.

+1

+1 멋지고 깨끗합니다. 테스트에서 어플리케이션 코드와 다른 특성 파일이 필요하거나 다른 테스트가 서로 다른 특성 파일을 필요로하는 경우에만 볼 수있는 유일한 문제점이 있습니다. 이것이 문제가된다면 Properties 객체를 설정 한 테스트를 작성한 다음 "실제"공간에 작성해야합니다. –

1

우리는 ResourceBundle.getString() 메소드를 조롱하는 시뮬레이션 문제가있었습니다.

java.util.MissingResourceException: Can't find resource for bundle $java.util.ResourceBundle$$EnhancerByMockitoWithCGLIB$$e9ea44f0, key name

우리의 문제는 방법은 mockito이 방법을 조롱하는 것이 불가능하게하는, 마지막이었다이었다. @PrepareForTest가 ({ClassThatCallsTheSystemClass.class이})이 ResourceBundle의 클래스 아님을 https://code.google.com/p/powermock/wiki/MockSystem

참고 :

대신 우리는이 soultion을 사용!

7

ResourceBundle.getBundle (String, ResourceBundle.Control)을 사용하면 ResourceBundle을 가져 와서 지정된 문자열에 대한 번들을 캐시 할 수 있습니다. ResourceBundle.Control을 하위 클래스 화하여 원하는 유형의 번들을 제공 할 수 있습니다.

@Test 
public void myTest() 
{ 
    // In your Test's init phase run an initial "getBundle()" call 
    // with your control. This will cause ResourceBundle to cache the result. 
    ResourceBundle rb1 = ResourceBundle.getBundle("blah", myControl); 

    // And now calls without the supplied Control will still return 
    // your mocked bundle. Yay! 
    ResourceBundle rb2 = ResourceBundle.getBundle("blah"); 
} 

여기에 서브 클래 싱 된 컨트롤의 :

ResourceBundle.Control myControl = new ResourceBundle.Control() 
{ 
    public ResourceBundle newBundle(String baseName, Locale locale, String format, 
      ClassLoader loader, boolean reload) 
    { 
     return myBundle; 
    } 
}; 

그리고 여기 (테스트는 독자들에게 연습 문제로 남겨 장치에 필요한 키/값으로 트리 맵을 작성)이 ResourceBundle을 조롱하는 한 가지 방법이다 :

ResourceBundle myBundle = new ResourceBundle() 
{ 
    protected void setParent(ResourceBundle parent) 
    { 
     // overwritten to do nothing, otherwise ResourceBundle.getBundle(String) 
     // gets into an infinite loop! 
    } 

    TreeMap<String, String> tm = new TreeMap<String, String>(); 

    @Override 
    protected Object handleGetObject(String key) 
    { 
     return tm.get(key); 
    } 

    @Override 
    public Enumeration<String> getKeys() 
    { 
     return Collections.enumeration(tm.keySet()); 
    } 
}; 
관련 문제