2012-07-20 4 views
14

Java 6, JUnit 4.8.1 및 콘솔 응용 프로그램 작성 중입니다. 내 응용 프로그램 내 서비스에서 하나 개의 메소드가 호출 될 때마다 (예를 들어, m_oppsSvc.getResults())이 같은 결과는 항상 반환되도록 행동을 조롱하려는 노출되지 않은 멤버 필드 ...Java : 해당 필드가 노출되지 않은 경우 필드의 메소드를 조롱하려면 어떻게해야합니까?

public class MyApp { 
    ... 
    private OpportunitiesService m_oppsSvc; 

    private void initServices() { 
     … 
     m_oppsSvc = new OpportunitiesServiceImpl(…); 
    } 
    ... 
} 

있습니다. 어떻게해야합니까? 이 필드에는 세터 메소드가 없습니다. 현재 Mockito 1.8.4와 협력 중입니다. Mockito 또는 다른 모의 프레임 워크를 사용하여이 작업을 수행 할 수 있습니까?

+0

당신이 아닌 setter 메소드를 만들 수는? – jrad

+0

[어떻게 단위 테스트 개인 방법합니까?] (http://programmers.stackexchange.com/questions/100959/how-do-you-unit-test-private-methods) 가능한 중복? –

+0

테스트 할 대상은 무엇입니까? 'getResults()'public입니까? 그것과 관련된 개인 필드가 있거나 런타임에 계산됩니까? 답변에 따라 '스파이'를 사용하거나 조롱하는 것과 관련이 없을 수도 있습니다. 그리고 'org.springframework.test.util.ReflectionTestUtils'와 같은 것을 사용하여 비공개 필드를 가치. – jhericks

답변

12

이 당신이 원하는 무엇인가 : 사용

@RunWith(MockitoJUnitRunner.class) 
public class MyAppTest { 

    @Mock private OpportunitiesService mocked_m_oppsSvc; 
    @InjectMocks MyApp myApp; 

    @Test public void when_MyApp_uses_OpportunititesService_then_verify_something() { 
     // given 
     given(mocked_m_oppsSvc.whatever()).willReturn(...); 

     // when 
     myApp.isUsingTheOpportunitiesService(...); 

     // then 
     verify... 
     assertThat... 
    } 
} 

: Mockito 1.9.0, BDD style, FEST-Assert AssertJ. 도움이 :) 이미 mockito를 사용하고있는 점을 감안

+0

@InjectMocks는 세터 주입 만 지원합니다. – Matt

+3

@InjectMocks는 개인 필드를 주입 ​​할 수도 있습니다. –

+1

Javadoc이 올바르지 않습니다. 항상 개인 필드 주입을 지원합니다. 그런 다음 세터 주입 후 1.9.0의 생성자 주입. InjectmMocks의 Javadoc 버전 1.9.0을 확인하십시오. http://docs.mockito.googlecode.com/hg/1.9.0/org/mockito/InjectMocks.html – Brice

-1

일반적으로 의존성 삽입을 사용하고 생성자, 별도의 설정자 또는 직접 메소드 (getResults)를 통해 mock 객체 (OppportunitiesServiceImpl 유형)를 전달해야합니다. 먼저 OpportunitiesServiceImpl에 대한 인터페이스를 추출해야 할 수 있습니다.

-1

일반적으로 종속성 주입을 사용하여 해결됩니다. 일반 (프로덕션) 모드에서는 의존성 주입 컨테이너 (예 : Spring 또는 Guice)가 OpportunitiesService의 인스턴스를 생성자 또는 설정자를 통해 MyApp에 삽입합니다.

그런 다음 테스트 할 때 동일한 setter 또는 constructor 인수를 사용하여 mock 인스턴스를 수동으로 "주입"할 수 있습니다. 대신

m_oppsSvc = new OpportunitiesServiceImpl(…); 

MyApp의 생성자

6

당신은 개인 필드 smell을 조롱하려는 시도를 고려해야 통해 OpportunitesService을 전달하려고 일을

. 즉, 현재 수행하려고 시도하는 작업이 올바르지 않거나 코드가 현재 올바르게 구성되지 않았다는 표시입니다. 다음과 같이

public class MyApp { 
    ... 
    private OpportunitiesService m_oppsSvc; 

    public MyApp(OpportunitiesService oppsSvc) { 
     this.m_oppsSvc = oppsSvc; 
    } 
    ... 
} 

이 테스트에서는 다음 모의를 삽입 할 수 있습니다 :

만 공개 방법이나 주입 의존성은 다음과 같이 주입 OpportunitiesService을 고려해야 제공 한 코드에서

을 조롱해야한다
OpportunitiesService mockOpportunitiesService = 
    Mockito.mock(OpportunitiesService.class); 
Mockit.when(mockOpportunitiesService.someMethod()).thenReturn(someValue); 
MyApp app = new MyApp(mockOpportunitiesService); 
0

당신은 JMockit와 함께 할 쉽게 할 수 있습니다

public class MyAppTest 
{ 
    @Tested MyApp myApp; 

    @Test 
    public testSomething(final @Capturing OpportunitiesService mockService) 
    { 
     new NonStrictExpectations() {{ 
      mockService.getResults(); result = asList("a", "b", "C"); 
      // record other expectations, if needed 
     }}; 

     myApp.whateverMethodIWantToTest(); 

     new Verifications() {{ 
      mockService.doSomething(anyInt); 
      // verify other expectations, if needed 
     }}; 
    } 
} 

구현 클래스 OpportunitiesServiceImpl이 테스트 코드에 언급되어 있지는 않지만 그 인스턴스 (그 수에 관계없이)는 여전히 적절하게 조롱을 얻습니다.

6

희망, 왜 리플렉션을 사용하지 :

@RunWith(MockitoJUnitRunner.class) 
public class MyApp { 

    @Mock 
    private OpportunitiesService m_oppsSvc; 

    private MyApp myApp; 


    @Before 
    public void before() throws Exception { 
     myApp = new MyApp(); 
     Field f = MyApp.class.getDeclaredField("m_oppsSvc"); 
     f.setAccessible(true); 
     f.set(myApp, m_oppsSvc); 
    } 
} 

그것은 조금 추한를하지만 트릭을 할 것입니다.이것이 Mockito를 사용하는 가장 효율적인 방법은 아닐 수도 있지만 작동 할 것입니다.

또한 Whitebox 클래스를 사용하여이 작업을 수행 할 수있는 Powermock도 있습니다. 나는 Powermock의 전체 세부 사항을받지 않습니다 그러나 여기 모의 객체 있어야 개인 필드 값을 삽입 할 수있는 호출입니다 :

Whitebox.setInternalState(myApp, "m_oppsSvc", m_oppsSvc); 
관련 문제