मॉकिटो: मॉक प्राइवेट फील्ड इनिशियलाइजेशन


94

मैं एक फील्ड वैरिएबल को कैसे मॉक कर सकता हूं जिसे इनिशियल इनलाइन किया जा रहा है?

class Test {
    private Person person = new Person();
    ...
    public void testMethod() {
        person.someMethod();
        ...
    }
}

यहां मैं person.someMethod()उस Test.testMethod()विधि का परीक्षण करते हुए मॉक करना चाहता हूं जिसके लिए मुझे personवेरिएबल के इनिशियलाइज़ेशन को मॉक करने की आवश्यकता है । कोई सुराग?

संपादित करें: मुझे व्यक्तिगत वर्ग को संशोधित करने की अनुमति नहीं है।


1
यह लिंक आपके लिए उपयोगी हो सकता है stackoverflow.com/questions/13645571/…
Popeye

2
आपको अपने कोड को रिफलेक्टर करना चाहिए ताकि आप इसके लिए मॉक पास कर सकें Person। विकल्प में ऐसा करने के लिए एक कंस्ट्रक्टर जोड़ना या एक सेटर विधि जोड़ना शामिल है।
टिम बेगेलिएसेन

जवाबों:


108

मॉकिटो आपको कुछ प्रतिबिंब बॉयलर प्लेट कोड को बचाने के लिए एक सहायक वर्ग के साथ आता है:

import org.mockito.internal.util.reflection.Whitebox;

//...

@Mock
private Person mockedPerson;
private Test underTest;

// ...

@Test
public void testMethod() {
    Whitebox.setInternalState(underTest, "person", mockedPerson);
    // ...
}

अद्यतन: दुर्भाग्य से मॉकिटो टीम ने मॉकिटो 2 में कक्षा को हटाने का फैसला किया । इसलिए आप अपना स्वयं का प्रतिबिंब बॉयलरप्लेट कोड लिखने के लिए वापस आ गए हैं, एक अन्य पुस्तकालय (जैसे अपाचे कॉमन्स लैंग ) का उपयोग करें, या बस व्हाइटबॉक्स वर्ग को देखें (यह एमआईटी लाइसेंस प्राप्त है )।

अद्यतन 2: JUnit 5 अपने स्वयं के प्रतिबिंब के साथ आता है और AnnotationSupport कक्षाएं जो उपयोगी हो सकती हैं और आपको अभी तक किसी अन्य पुस्तकालय में खींचने से बचा सकती हैं।


मैं अन्य कारणों की वजह से अपनी लक्षित वस्तु की जासूसी कर रहा हूं और इस मामले में जब मेरी वस्तु जासूसी कर रही है, मैं इस तरह से आंतरिक स्थिति निर्धारित नहीं कर सकता।
अरुण

क्यों नहीं? मैं इसका इस्तेमाल जासूसों के साथ कर रहा हूं। एक व्यक्ति उदाहरण बनाएँ। ठूंठ की जो भी जरूरत हो, उसे अपने टेस्ट उदाहरण पर सेट करें।
राल्फ

चेतावनी: व्हाइटबॉक्स internalपैकेज में है और मॉकिटो 2.6.2 पर अब काम नहीं करता है।
नोवा

आप FieldSetter.setField () का उपयोग कर सकते हैं। मैंने उसी के लिए नीचे एक उदाहरण दिया है।
राज कुमार

1
@Ralf क्योंकि जावा में एक संदर्भ नाम बदलने से हमेशा संकलन त्रुटि होती है।
जो कोडर

67

पार्टी के लिए बहुत देर हो चुकी थी, लेकिन मुझे यहाँ मारा गया और एक दोस्त से मदद मिली। बात पॉवरमॉक का इस्तेमाल करने की नहीं थी। यह मॉकिटो के नवीनतम संस्करण के साथ काम करता है।

मॉकिटो इसी के साथ आता है org.mockito.internal.util.reflection.FieldSetter

यह मूल रूप से क्या करता है आपको प्रतिबिंब का उपयोग करके निजी क्षेत्रों को संशोधित करने में मदद करता है।

आप इसका उपयोग कैसे करते हैं:

@Mock
private Person mockedPerson;
private Test underTest;

// ...

@Test
public void testMethod() {
    FieldSetter.setField(underTest, underTest.getClass().getDeclaredField("person"), mockedPerson);
    // ...
    verify(mockedPerson).someMethod();
}

इस तरह आप एक मॉक ऑब्जेक्ट को पास कर सकते हैं और फिर बाद में उसे सत्यापित कर सकते हैं।

यहाँ संदर्भ है।


FieldSetterमॉकिटो 2.x में अब उपलब्ध नहीं है।
राल्फ

4
@Ralf मैं संस्करण mockito-core-2.15.0 का उपयोग कर रहा हूं। यह वहां उपलब्ध है। static.javadoc.io/org.mockito/mockito-core/2.0.15-beta/org/… । फिर भी बीटा।
राज कुमार

1
@ राजकुमार Class#getDeclaredFieldएकल परम को स्वीकार करते हैं , इसलिए परनों को इस तरह से देखने की जरूरत है FieldSetter.setField(underTest, underTest.getClass().getDeclaredField("person"), mockedPerson);। यही कारण है कि मुझे यह गलत लगा और आपके उदाहरण में इसे ठीक करने के लिए एक अच्छा विचार हो सकता है। जवाब के लिए धन्यवाद।
डापेंग ली

1
आंतरिक एपीआई का उपयोग करना सबसे अच्छा विचार नहीं है
डेविड

@ राजकुमार नाइस, लेकिन जैसा कि ज़ीम्बो रॉजर ने उल्लेख किया है: क्या आंतरिक एपीआई का उपयोग करना अच्छा है? यह आंतरिक रूप से क्यों है? यह परीक्षण के लिए बहुत उपयोगी है।
विली मेंजेल

31

मामले में आप स्प्रिंग टेस्ट ट्राई करें। org.springframework.test.util.ReflectionTestUtils

 ReflectionTestUtils.setField(testObject, "person", mockedPerson);

1
महान! इस लेख से लिंक करने में मदद कर सकते हैं और शायद इसमें से एक निर्भरता भी शामिल है: baeldung.com/spring-reflection-test-utils
Willi Mentzel

build.gradle.kts:testImplementation("org.springframework:spring-test:5.1.2.RELEASE")
विल्ली मेंजेल

28

मुझे इस समस्या का हल पहले ही मिल गया जिसे मैं यहाँ पोस्ट करना भूल गया।

@RunWith(PowerMockRunner.class)
@PrepareForTest({ Test.class })
public class SampleTest {

@Mock
Person person;

@Test
public void testPrintName() throws Exception {
    PowerMockito.whenNew(Person.class).withNoArguments().thenReturn(person);
    Test test= new Test();
    test.testMethod();
    }
}

इस समाधान के मुख्य बिंदु हैं:

  1. PowerMockRunner के साथ मेरे परीक्षण मामलों को चलाना: @RunWith(PowerMockRunner.class)

  2. पावरमॉक को Test.classनिजी क्षेत्रों के हेरफेर के लिए तैयार करने का निर्देश दें :@PrepareForTest({ Test.class })

  3. और अंत में व्यक्ति वर्ग के लिए निर्माणकर्ता का मज़ाक उड़ाएँ:

    PowerMockito.mockStatic(Person.class); PowerMockito.whenNew(Person.class).withNoArguments().thenReturn(person);


7
आपका स्पष्टीकरण mockStaticफ़ंक्शन के बारे में बात करता है, लेकिन यह आपके कोड उदाहरण में प्रतिनिधित्व नहीं करता है। क्या कोड उदाहरण में mockStaticकॉल होनी चाहिए , या क्या यह निर्माणकर्ताओं के लिए आवश्यक नहीं है?
शादिनिजा

10

REST क्लाइंट मॉक में मैपर को इनिशियलाइज़ करने के लिए निम्न कोड का उपयोग किया जा सकता है। mapperक्षेत्र निजी है और इकाई परीक्षण सेटअप के दौरान निर्धारित करने की आवश्यकता।

import org.mockito.internal.util.reflection.FieldSetter;

new FieldSetter(client, Client.class.getDeclaredField("mapper")).set(new Mapper());

5

यदि आप चर को सभी परीक्षणों के लिए समान मान सेट करने की आवश्यकता है, तो @ जरदा के मार्गदर्शक का उपयोग करके आप इसे परिभाषित कर सकते हैं:

@Before
public void setClientMapper() throws NoSuchFieldException, SecurityException{
    FieldSetter.setField(client, client.getClass().getDeclaredField("mapper"), new Mapper());
}

लेकिन सावधान रहें कि निजी मूल्यों को अलग करने के लिए देखभाल के साथ संभाला जाना चाहिए। यदि वे निजी हैं तो किसी कारण से।

उदाहरण के लिए, मैं इसका उपयोग करता हूं, उदाहरण के लिए, यूनिट परीक्षणों में नींद के प्रतीक्षा समय को बदलने के लिए। वास्तविक उदाहरणों में मैं 10 सेकंड के लिए सोना चाहता हूं, लेकिन यूनिट-टेस्ट में अगर यह तत्काल है तो मैं संतुष्ट हूं। एकीकरण परीक्षणों में आपको वास्तविक मूल्य का परीक्षण करना चाहिए।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.