2011-08-06 2 views
0

JUnit/Mockito로 테스트하고 싶은 메소드가 있습니다.메소드를 테스트 할 때 해당 메소드가 참조하는 싱글 톤에서 변수를 모의 할 수 있습니까?

이 메서드는 하나의 정수, numberOfRowsThatTheUserWants을 사용합니다.

그런 다음이 값을 다른 값인 totalNumberOfRowsInDB과 비교하여 요청 된 행 수 (임의로 선택됨)를 반환합니다. 사용자가 사용할 수있는 것 이상을 요청하면 사용 가능한 합계 만 가져옵니다.

이 시점까지는 모두 문제가 없습니다.

문제는이 메서드 동작을 테스트하고 있습니다.

totalNumberOfRowsInDB은 싱글 톤에서 유지되는 변수입니다. 이 작업을 수행하는 이유는 시작시 설정되어 응용 프로그램을 실행하는 동안 변경되지 않기 때문입니다. 변경하지 않을 행을 계속 계산하려면 DB에 대한 일정한 unneccssay 호출을 피하고 싶었습니다.

테스트는 총 10 개의 행이 있다고 가정하면 테스트가 작동하지만 (실제로 기본에있는 것과 같이) 내 테스트가 내 스크럽 데이터에 종속되지 않게하려면 if 몇 줄을 더 추가하면 테스트가 중단됩니다.

질문 : 실제로 테스트하려는 메소드의 내부에있는 정적 변수를 수정 (모의) 할 수 있습니까? 나는 .../그 지독하게 잘못 경우 내 디자인을 개선하는 방법에 대한 조언 제안을 완전히 열려있어

이 내 문제의 단순화 된 버전 보여줄 수있는 작은 데모입니다 : 반사를 사용

public class MockMe 
{ 
    public static void main(String[] args) 
    { 
     // Setting to 5, but this comes from user input 
     Integer numberOfRowsThatTheUserWants = 5; 
     MockMe myMockMe = new MockMe(); 
     myMockMe.myMethod(numberOfRowsThatTheUserWants); 
    } 

    private void myMethod(Integer numberOfRowsThatTheUserWants) 
    { 
     if(numberOfRowsThatTheUserWants > MySingleton.getInstance().getTotalRowsOnDB()) 
     { 
      System.out.println("You've requested more than is available, so I'll just give you all I've got instead"); 
     } 
     else 
     { 
      System.out.println("Here are your " + numberOfRowsThatTheUserWants + " rows as requested, sir!"); 
     } 
    } 
} 

class MySingleton 
{ 
    private static MySingleton mySingleton; 
    private int totalRowsOnDB; 

    private MySingleton() 
    { 
     //private constructor to prevent instantiation 
    } 

    public int getTotalRowsOnDB() 
    { 
     return totalRowsOnDB; 
    } 

    public static MySingleton getInstance() 
    { 
     if (mySingleton == null) 
     { 
      mySingleton = new MySingleton(); 
      // this is actually set by SELECT COUNT(*) FROM TABLENAME but setting to 10 for purposes of demo 
      //DBManager dbManager = new DBManagerImpl(); 
      //mySingleton.totalRowsOnDB = dbManager.getTotalRows(); 
      mySingleton.totalRowsOnDB = 10; 
     } 
     return mySingleton; 
    } 
} 
+0

테스트를 "실제"데이터에 종속 시키려고합니까? 즉, 표의 실제 행 수는? 정확히 무엇을 '모의'하고 싶은지 확실하지 않지만 실제 데이터와 비 문질러진 데이터를 원할 경우 "순수한 단위 테스트"의 경계를 뛰어 넘을 것입니다. 이는 어떤 캠프에서 왔는지에 따라 다릅니다. if 테스트중인 유닛은 "외부 세계"와 아무런 관련이없는 격리 된 상태에서 테스트되어야합니다. 그러면 값을 "조롱"해야하지만 실제 카운트를 기반으로하기를 원한다면 통합 테스트의 영역에서 (추종자들의 POV에 따라) – PhD

답변

2

이가 시작할 때 설정 될 것이기 때문이었다 응용 프로그램을 실행하는 동안 변경하지 않을 일에 대한 나의 이유

그런 경우에는이 속성에 대한 setter를 노출하는 것이 좋습니다. 그렇다면 클래스를 확실히 "테스트 할 수 있습니다". 그런 목적을위한 싱글 톤을 쓰는 것은 제 의견으로는별로 좋은 생각이 아닙니다.

어쨌든 단위 테스트 (예 : 프로덕션 코드에서 autowired) 용 클래스의 비공개 필드를 수정하는 경우 org.springframework.test.util.ReflectionTestUtils과 같이 사용할 수 있습니다 (또는 코드를 기반으로 사용자의 반사 솔루션을 작성할 수 있습니다).

2

을 , 당신은 개인 필드를 수정할 수 있습니다

Field field = MySingleton.class.getDeclaredField("totalRowsOnDB"); 
field.setAccessible(true); // "Cheat" by setting it to "not private" 
field.set(MySingleton.class, 5); // Set it to whatever you like 
관련 문제