2011-11-08 16 views
23

कहलाती है, मैं एक निजी विधि बनाने के लिए मजाक करने की कोशिश कर रहा हूं जो जेएनडीआई कॉल कर रहा है। जब उस विधि को यूनिट परीक्षण से बुलाया जाता है, तो यह अपवाद फेंकता है ^। मैं परीक्षण उद्देश्यों के लिए उस विधि को नकल करना चाहता हूं। मैंने sample code from another questions answer का उपयोग किया, और परीक्षण पास होने पर, ऐसा लगता है कि अंतर्निहित विधि अभी भी कॉल हो जाती है। मैंने doTheGamble() विधि में System.err.println() डाला, और यह मेरे कंसोल पर मुद्रित हो जाता है।पावरमोक के साथ मॉक निजी विधि, लेकिन अंतर्निहित विधि अभी भी

दिलचस्प है, अगर मैं पहले assertThat पर टिप्पणी करता हूं, तो परीक्षण पास हो जाता है। ? :(

तो, मैं कैसे एक निजी विधि बाहर नकली है इतना है कि यह कहा जाता है नहीं प्राप्त करता है?

import static org.hamcrest.core.Is.is; 
import static org.junit.Assert.assertThat; 
import static org.mockito.Matchers.anyInt; 
import static org.mockito.Matchers.anyString; 
import static org.powermock.api.mockito.PowerMockito.when; 
import static org.powermock.api.support.membermodification.MemberMatcher.method; 

import java.util.Random; 

import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.powermock.api.mockito.PowerMockito; 
import org.powermock.core.classloader.annotations.PrepareForTest; 
import org.powermock.modules.junit4.PowerMockRunner; 

@RunWith(PowerMockRunner.class) 
@PrepareForTest(CodeWithPrivateMethod.class) 
public class PowerMock_Test { 

    static boolean gambleCalled = false; 

    @Test(expected = RuntimeException.class) 
    public void when_gambling_is_true_then_always_explode() throws Exception { 
     CodeWithPrivateMethod spy = PowerMockito.spy(new CodeWithPrivateMethod()); 

     when(spy, method(CodeWithPrivateMethod.class, "doTheGamble", String.class, int.class)) 
       .withArguments(anyString(), anyInt()) 
       .thenReturn(true); 

/* 1 */ assertThat(PowerMock_Test.gambleCalled, is(false)); 
     spy.meaningfulPublicApi(); 
/* 2 */ assertThat(PowerMock_Test.gambleCalled, is(false)); 
    } 
} 


class CodeWithPrivateMethod { 

    public void meaningfulPublicApi() { 
     if (doTheGamble("Whatever", 1 << 3)) { 
      throw new RuntimeException("boom"); 
     } 
    } 

    private boolean doTheGamble(String whatever, int binary) { 
     Random random = new Random(System.nanoTime()); 
     boolean gamble = random.nextBoolean(); 

     System.err.println("\n>>> GAMBLE CALLED <<<\n"); 
     PowerMock_Test.gambleCalled = true; 

     return gamble; 
    } 
} 

^जाहिर है, के बाद से मेरी कार्यक्षेत्र JNDI का समर्थन नहीं करता, केवल उत्पादन वातावरण

करता है

% मैं एक नकली वस्तु के निर्माण के लिए सभी पुस्तकालय, JUnit 4.10, Mockito 1.8.5, Hamcrest 1.1, Javassist 3.15.0, और PowerMock 1.4.10।

उत्तर

29

PowerMock Private Method Example से:

@RunWith(PowerMockRunner.class) 
// We prepare PartialMockClass for test because it's final or we need to mock private or static methods 
@PrepareForTest(PartialMockClass.class) 
public class YourTestCase { 
@Test 
public void privatePartialMockingWithPowerMock() {   
    PartialMockClass classUnderTest = PowerMockito.spy(new PartialMockClass()); 

    // use PowerMockito to set up your expectation 
    PowerMockito.doReturn(value).when(classUnderTest, "methodToMock", "parameter1"); 

    // execute your test 
    classUnderTest.execute(); 

    // Use PowerMockito.verify() to verify result 
    PowerMockito.verifyPrivate(classUnderTest, times(2)).invoke("methodToMock", "parameter1"); 
} 

तो अपने कोड को यह लागू करने के लिए, मुझे लगता है कि यह हो सकता है:

@RunWith(PowerMockRunner.class) 
@PrepareForTest(CodeWithPrivateMethod.class) 
public class PowerMock_Test { 
    @Test(expected = RuntimeException.class) 
    public void when_gambling_is_true_then_always_explode() throws Exception { 
     CodeWithPrivateMethod spy = PowerMockito.spy(new CodeWithPrivateMethod()); 

     PowerMockito.doReturn(true).when(spy, "doTheGamble", anyString(), anyInt()); 


/* 1 */ PowerMockito.verifyPrivate(spy, times(0)).invoke("doTheGamble", anyString(), anyInt());    
     spy.meaningfulPublicApi(); 
/* 2 */ PowerMockito.verifyPrivate(spy, times(2)).invoke("doTheGamble", anyString(), anyInt());    
    } 
} 

मैं सिर्फ संपादक में यहाँ कि कोडित। वास्तव में कोई परीक्षण नहीं चला है, और इस कोड के क्राफ्टिंग में कोई भी बग नुकसान नहीं पहुंचा है।

+8

+1 बग की हानि के लिए +1। आप की बहुत देखभाल;) – Guillaume

+0

@ माइक क्या आपको कोई विचार है कि क्यों करें 'सचमुच (सत्य)। जब (जासूसी, "doTheGamble", anyString(), anyInt());' काम करता है लेकिन 'doReturn (true)। (Spy , विधि (CodeWithPrivateMethod.class, "doTheGamble", String.class, int.class)) .withArguments (anyString(), anyInt()); '' अवैध अर्ग्यूमेंट अपवाद: तर्क प्रकार मिस्चैच 'में परिणाम? उत्तरार्द्ध उदाहरण की शैली और कम से कम समकक्ष रखने में अधिक लगता है लेकिन काम नहीं करता है। – ArtB

+0

मैं ईमानदारी से नहीं कर सकता, क्षमा करें। मैं मॉकिटो/पावरमोक के लिए अपेक्षाकृत नया हूं ... मैंने कभी उस शैली में कोड लिखने का प्रयास नहीं किया है ('.withArguments (...)') पहले। – Mike

0

जब आप spy का उपयोग के नवीनतम संस्करण का उपयोग कर रहा, यह एक वास्तविक आधा समर्थित वस्तु है। मेरा अनुमान होगा spy से छुटकारा पाने के लिए। शुद्ध नकली वस्तु पर काम करें।

+1

मैं जासूसी कर रहे वर्ग के कार्यान्वयन का परीक्षण करने की कोशिश कर रहा हूं, इसलिए यह एक विकल्प नहीं है। – ArtB

1

ArtB,

आप सुनिश्चित करें कि आपके कोड काम नहीं करता हैं (या) मैं यहाँ कुछ याद आ रही है? मैं अभी जिस तरह माइक सुझाव के बाद एक के साथ अपने विधि उम्मीद की जगह है और यह ठीक काम करता है:

PowerMockito.doReturn(true).when(spy, 
       method(CodeWithPrivateMethod.class, "doTheGamble", String.class, int.class)) 
       .withArguments(anyString(), anyInt()); 

मैं Powermockito इस्तेमाल कभी नहीं किया लेकिन इससे पहले कि Mockito एक बहुत इस्तेमाल किया।

+0

हाँ मुझे यकीन है, मैं काम करने के बाद पेस्ट कर दूंगा कुछ आउटपुट। – ArtB

2

ArtB,

बस पूरा कोड है जो मेरे ग्रहण आईडीई में ठीक काम करता है चिपकाने। मैंने अपनी आखिरी पोस्ट में केवल उम्मीद को बदल दिया है। सौभाग्य।

import static org.hamcrest.core.Is.is; 
import static org.junit.Assert.assertThat; 
import static org.mockito.Matchers.anyInt; 
import static org.mockito.Matchers.anyString; 
import static org.powermock.api.support.membermodification.MemberMatcher.method; 

import java.util.Random; 

import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.powermock.api.mockito.PowerMockito; 
import org.powermock.core.classloader.annotations.PrepareForTest; 
import org.powermock.modules.junit4.PowerMockRunner; 

@RunWith(PowerMockRunner.class) 
@PrepareForTest(CodeWithPrivateMethod.class) 
public class PowerMock_Test { 

    static boolean gambleCalled = false; 

    @Test(expected = RuntimeException.class) 
    public void when_gambling_is_true_then_always_explode() throws Exception { 
     CodeWithPrivateMethod spy = PowerMockito.spy(new CodeWithPrivateMethod()); 

//  PowerMockito.doReturn(true).when(spy, "doTheGamble", anyString(), anyInt()); 

     PowerMockito.doReturn(true).when(spy, 
       method(CodeWithPrivateMethod.class, "doTheGamble", String.class, int.class)) 
       .withArguments(anyString(), anyInt()); 

     assertThat(PowerMock_Test.gambleCalled, is(false)); 
     spy.meaningfulPublicApi(); 
     assertThat(PowerMock_Test.gambleCalled, is(false)); 
    } 
} 


class CodeWithPrivateMethod { 

    public void meaningfulPublicApi() { 
     if (doTheGamble("Whatever", 1 << 3)) { 
      throw new RuntimeException("boom"); 
     } 
    } 

    private boolean doTheGamble(String whatever, int binary) { 
     Random random = new Random(System.nanoTime()); 
     boolean gamble = random.nextBoolean(); 

     System.err.println("\n>>> GAMBLE CALLED <<<\n"); 
     PowerMock_Test.gambleCalled = true; 

     return gamble; 
    } 
}