Unneccessary Stubbing अपवाद को कैसे हल करें


101

मेरा कोड नीचे है,

@RunWith(MockitoJUnitRunner.class)
public class MyClass {

    private static final String code ="Test";

    @Mock
     private MyClassDAO dao;

    @InjectMocks
     private MyClassService Service = new MyClassServiceImpl();

    @Test
     public void testDoSearch() throws Exception {
         final String METHOD_NAME = logger.getName().concat(".testDoSearchEcRcfInspections()");
         CriteriaDTO dto = new CriteriaDTO();
         dto.setCode(code);
         inspectionService.searchEcRcfInspections(dto);
         List<SearchCriteriaDTO> summaryList = new ArrayList<SearchCriteriaDTO>();
         inspectionsSummaryList.add(dto);
         when(dao.doSearch(dto)).thenReturn(inspectionsSummaryList);//got error in this line
         verify(dao).doSearchInspections(dto);

      }
}

मैं नीचे अपवाद हो रही है

org.mockito.exceptions.misusing.UnnecessaryStubbingException: 
Unnecessary stubbings detected in test class: Test
Clean & maintainable test code requires zero unnecessary code.
Following stubbings are unnecessary (click to navigate to relevant line of code):
  1. -> at service.Test.testDoSearch(Test.java:72)
Please remove unnecessary stubbings or use 'silent' option. More info: javadoc for UnnecessaryStubbingException class.
  at org.mockito.internal.exceptions.Reporter.formatUnncessaryStubbingException(Reporter.java:838)
  at org.mockito.internal.junit.UnnecessaryStubbingsReporter.validateUnusedStubs(UnnecessaryStubbingsReporter.java:34)
  at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:49)
  at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:103)
  at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
  at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
  at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
  at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
  at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
  at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

कृपया मेरी मदद करें कि कैसे हल करें

जवाबों:


120

बदलें @RunWith(MockitoJUnitRunner.class)के साथ @RunWith(MockitoJUnitRunner.Silent.class)


44
स्वागत हे। यह बताने के लिए कि वे ओपी को इस तरह के कोड को क्यों बदलना चाहिए, अपने उत्तर को अपडेट करने के लिए अच्छी तरह से लायक होगा । इससे उन्हें और भावी आगंतुकों को समझने में मदद मिलेगी।
कीड़े

5
Btw, यह @RunWith(MockitoJUnitRunner.Silent.class)और नहीं चुप
fgysin को फिर से बहाल मोनिका

6
कोटलिन में:@RunWith(MockitoJUnitRunner.Silent::class)
जुआन साराविया

9
निश्चित नहीं कि यह उत्तर बिना स्पष्टीकरण के क्यों उठता रहता है। अन्य उत्तर अधिक सार्थक और सटीक हैं।
योगेश

8
यह समस्या को हल नहीं करता है, लेकिन बस त्रुटि संदेश को दबाता है और कक्षा में अन्य सभी परीक्षणों (यदि कोई हो) को भी प्रभावित करेगा।
फेंसर

99

सबसे पहले आपको अपने परीक्षण तर्क की जांच करनी चाहिए। आमतौर पर 3 मामले हैं। सबसे पहले, आप गलत तरीके का मजाक उड़ा रहे हैं (आपने एक टाइपो बनाया है या किसी ने परीक्षण किया कोड बदल दिया है ताकि नकली विधि का उपयोग न हो)। दूसरा, इस पद्धति को कॉल करने से पहले आपका परीक्षण विफल हो रहा है। तीसरा, आपको तर्क गलत लगता है अगर / शाखा को कोड में कहीं स्विच किया जाता है ताकि नकली विधि को न बुलाया जाए।

यदि यह पहला मामला है, तो आप हमेशा कोड में उपयोग किए गए के लिए नकली विधि को बदलना चाहते हैं। दूसरे और तीसरे के साथ यह निर्भर करता है। आमतौर पर आपको इस मॉक को बस डिलीट कर देना चाहिए अगर इसका कोई उपयोग नहीं है। लेकिन कभी-कभी पैराट्राइज्ड परीक्षणों में कुछ मामले होते हैं, जिन्हें यह अलग रास्ता अपनाना चाहिए या पहले असफल होना चाहिए। फिर आप इस परीक्षण को दो या दो से अधिक अलग-अलग भागों में विभाजित कर सकते हैं लेकिन यह हमेशा अच्छा नहीं होता है। संभवतः 3 तर्कों के साथ 3 परीक्षण विधियां आपको परीक्षण को अपठनीय बना सकती हैं। JUnit 4 के लिए उस मामले में आप या तो इस अपवाद को चुप कर देते हैं

@RunWith(MockitoJUnitRunner.Silent.class) 

एनोटेशन या यदि आप नियम दृष्टिकोण का उपयोग कर रहे हैं

@Rule
public MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.LENIENT);

या (समान व्यवहार)

@Rule
public MockitoRule rule = MockitoJUnit.rule().silent();

JUnit 5 परीक्षणों के लिए आप mockito-junit-jupiterपैकेज में दिए गए एनोटेशन का उपयोग करके इस अपवाद को चुप कर सकते हैं ।

@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
class JUnit5MockitoTest {
}

3
@MockitoSettings (सख्ती = सख्ती)। मेरे सेटअप में कठोरता को समायोजित करने का सबसे सरल तरीका है। धन्यवाद!
मैट

4
यह उत्तर संभावनाओं का अच्छा अवलोकन प्रदान करता है। हालाँकि, आप केस के आधार पर मामले के आधार पर उदारता की सख्ती भी निर्धारित कर सकते हैं Mockito.lenient().when(...); इस विशेष प्रश्न के लिए यह होगाMockito.lenient().when(dao.doSearch(dto)).thenReturn(inspectionsSummaryList);
neXus

सुपरक्लास और सबक्लासेस में मॉकिटोसेटिंग में एक्सटेंडविथ को परिभाषित करें, जब परीक्षण पदानुक्रम के साथ काम करते हैं। आशा है कि यह मेरे खर्च पर किसी के लिए समय बचाता है।
चमत्कार_थे_ वीवी

34

मौन कोई हल नहीं है। आपको अपने परीक्षण में अपने नकली को ठीक करने की आवश्यकता है। आधिकारिक दस्तावेज यहां देखें ।

अनावश्यक स्टब्स स्टब्ड मेथड कॉल हैं जिन्हें परीक्षण निष्पादन के दौरान कभी महसूस नहीं किया गया था (मॉकिटो हिंट भी देखें), उदाहरण:

//code under test:
 ...
 String result = translator.translate("one")
 ...

 //test:
 ...
 when(translator.translate("one")).thenReturn("jeden"); // <- stubbing realized during code execution
 when(translator.translate("two")).thenReturn("dwa"); // <- stubbing never realized
 ...

ध्यान दें कि परीक्षण के निष्पादन के दौरान, कोड में परीक्षण के दौरान, स्टब किए गए तरीकों में से एक का कभी भी एहसास नहीं हुआ था। आवारा स्टबिंग डेवलपर, कॉपी-पेस्ट की कलाकृतियों या परीक्षण / कोड को न समझने वाले प्रभाव का निरीक्षण हो सकता है। किसी भी तरह से, डेवलपर अनावश्यक परीक्षण कोड के साथ समाप्त होता है। कोडबेस को साफ-सुथरा बनाए रखने के लिए अनावश्यक कोड हटाना आवश्यक है। अन्यथा परीक्षण पढ़ने में कठिन होते हैं और इसके बारे में कारण।

अप्रयुक्त स्टबिंग का पता लगाने के बारे में अधिक जानने के लिए मॉकिटोहिंट देखें।


13
ऐसी कई स्थितियाँ हैं जहाँ आप एक समान @BeforeEach सेटअप के विरुद्ध 8-9 परीक्षण लिखते हैं जहाँ एक स्टब से लौटाया गया आइटम मुट्ठी भर परीक्षणों पर व्यावसायिक तर्क के कारण अप्रयुक्त होता है। आप या तो (ए) इसे कई परीक्षणों में तोड़ सकते हैं और प्रभावी रूप से एक आइटम (बी) कॉपी / पेस्ट कर सकते हैं (एकल) कॉपी करें / चिपकाएँ उस एकल पंक्ति को कॉपी करें जिसे मॉकिटो 6 परीक्षणों के लिए ईएमओ है जो इसका उपयोग करते हैं और इसे करते हैं 2 में नहीं है कि या नहीं (सी) चुप का उपयोग करें। मैं मौन / चेतावनी का उपयोग करना पसंद करता हूं। यह एक टूटी हुई परीक्षा नहीं है।
RockMeetHardplace

1
@RockMeetHardplace, साइलेंट एक समाधान नहीं है , जल्दी से आप कम कॉपी / पेस्ट देखते हैं , लेकिन जब आपके प्रोजेक्ट पर नए लोगों द्वारा अपने परीक्षण बनाए रखते हैं तो यह समस्याग्रस्त होगा। अगर मॉकिटो किताबों की दुकान है कि यह कुछ भी नहीं के लिए है।
स्टीफन ग्रिलोन

2
@sgrillon: लेकिन यह प्रणाली गलत-सकारात्मक के भार का पता लगाती है। यही है, यह कहता है कि कुछ अप्रयुक्त है, लेकिन यह स्पष्ट रूप से नहीं है, क्योंकि स्टब हटाने से निष्पादन टूट जाता है। ऐसा नहीं है कि परीक्षण कोड में सुधार नहीं किया जा सकता है, यह है कि स्टबिंग की एक महत्वपूर्ण रेखा को "अनावश्यक" के रूप में कभी भी पता नहीं लगाया जाना चाहिए । इसलिए इस चेक को निष्क्रिय करने में सक्षम होने का महत्व, यह बहुत उत्सुक है।
कारिघन

@ करिधन, अगर आपके नकली को गलत के रूप में पाया जाता है, तो यह वैसा नहीं हो सकता जैसा आप सोचते हैं। यह आपको एक ओके टेस्ट देता है जबकि एक बग हो सकता है।
स्टीफन ग्रिलोन

@sgrillon, क्षमा करें, मैं उस पर आपके पास कभी नहीं गया। यह पता चला है कि इस के साथ एक बग हुआ करता था जहां परीक्षण निष्पादन आदेश के आधार पर यह "झूठी हिट" उत्पन्न करेगा, जहां एक परीक्षण में उपयोग किए जाने वाले स्टब्स लेकिन दूसरे में लिखे गए इसे ट्रिगर करेंगे। हालांकि यह लंबे समय से तय है, जहां तक ​​मैं बता सकता हूं।
कारिघन

27

मेरे लिए @Ruleन तो @RunWith(MockitoJUnitRunner.Silent.class)सुझावों ने काम किया। यह एक विरासत परियोजना थी जहां हमने मॉकिटो-कोर 2.23.0 में अपग्रेड किया।

हम UnnecessaryStubbingExceptionउपयोग करके छुटकारा पा सकते हैं :

Mockito.lenient().when(mockedService.getUserById(any())).thenReturn(new User());

के बजाय:

when(mockedService.getUserById(any())).thenReturn(new User());

यह कहने की आवश्यकता नहीं है कि आपको परीक्षण कोड को देखना चाहिए, लेकिन हमें सामान संकलित करने और सबसे पहले चलने वाले परीक्षणों की आवश्यकता है);


6
IMHO। यह यहाँ सबसे अधिक उपयोग का उत्तर है जो मुझे पूरे परीक्षण वर्ग को चुप कराने के बजाय मिला है।
प्रियादेशधर

चूंकि मैं केवल 1 मॉकिंग को दबाना चाहता था, इसलिए यह मेरे लिए सबसे अच्छा जवाब है। हालांकि ओपी के लिए वास्तव में एक जवाब नहीं है।
हंस वाउटर्स

25
 when(dao.doSearch(dto)).thenReturn(inspectionsSummaryList);//got error in this line
 verify(dao).doSearchInspections(dto);

whenयहाँ कुछ करने के लिए अपने नकली कॉन्फ़िगर करता है। हालाँकि, आप इस लाइन के बाद किसी भी तरह से इस मॉक का उपयोग नहीं करते (इसके अलावा a verify)। मॉकिटो आपको चेतावनी देता है कि whenरेखा व्यर्थ है। शायद आपने एक तर्क त्रुटि की है?


आपकी मदद के लिए धन्यवाद
VHS

मुझे दोनों की आवश्यकता है जब बयानों को सत्यापित करने के लिए कृपया सुझाव दें कि आगे कैसे बढ़ना है
VHS

2
अपने परीक्षण वर्ग ( Service) पर एक फ़ंक्शन को कॉल करें यह देखने के लिए कि क्या यह सही ढंग से प्रतिक्रिया करता है। आपने ऐसा बिल्कुल नहीं किया, इसलिए आप यहाँ क्या परीक्षण कर रहे हैं?
जॉन 16384

3

अपने स्टैक ट्रेस के एक हिस्से को देखकर ऐसा लगता है जैसे आप dao.doSearch()कहीं और ठूंसे हुए हैं। अधिक बार-बार एक ही विधि के स्टब्स बनाना।

Following stubbings are unnecessary (click to navigate to relevant line of code):
  1. -> at service.Test.testDoSearch(Test.java:72)
Please remove unnecessary stubbings or use 'silent' option. More info: javadoc for UnnecessaryStubbingException class.

उदाहरण के लिए नीचे टेस्ट क्लास पर विचार करें:

@RunWith(MockitoJUnitRunner.class)
public class SomeTest {
    @Mock
    Service1 svc1Mock1;

    @Mock
    Service2 svc2Mock2;

    @InjectMock
    TestClass class;

    //Assume you have many dependencies and you want to set up all the stubs 
    //in one place assuming that all your tests need these stubs.

    //I know that any initialization code for the test can/should be in a 
    //@Before method. Lets assume there is another method just to create 
    //your stubs.

    public void setUpRequiredStubs() {
        when(svc1Mock1.someMethod(any(), any())).thenReturn(something));
        when(svc2Mock2.someOtherMethod(any())).thenReturn(somethingElse);
    }

    @Test
    public void methodUnderTest_StateUnderTest_ExpectedBehavior() {
        // You forget that you defined the stub for svcMock1.someMethod or 
        //thought you could redefine it. Well you cannot. That's going to be 
        //a problem and would throw your UnnecessaryStubbingException.
       when(svc1Mock1.someMethod(any(),any())).thenReturn(anyThing);//ERROR!
       setUpRequiredStubs();
    }
}

मैं जहाँ आवश्यक हो, स्टब करने के लिए अपने परीक्षणों को फिर से शुरू करने पर विचार कर रहा हूँ


2

यदि आप इसके बजाय इस शैली का उपयोग कर रहे हैं:

@Rule
public MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);

इसे इसके साथ बदलें:

@Rule
public MockitoRule rule = MockitoJUnit.rule().silent();

2

बदलने के

@RunWith(MockitoJUnitRunner.class)

साथ में

@RunWith(MockitoJUnitRunner.Silent.class)

या हटा दें@RunWith(MockitoJUnitRunner.class)

या अनचाहे नकली कॉल (अनधिकृत स्टबिंग के रूप में दिखाया गया है) पर टिप्पणी करें।


1

मेरे पास UnnecessaryStubbingExceptionतब था जब मैंने whenस्पाई ऑब्जेक्ट पर विधियों का उपयोग करने की कोशिश की । Mockito.lenient()अपवाद को चुप कर दिया लेकिन परीक्षण के परिणाम सही नहीं थे।

जासूस वस्तुओं के मामले में, किसी को सीधे तरीकों को कॉल करना होगा।

@ExtendWith(MockitoExtension.class)
@RunWith(JUnitPlatform.class)
class ArithmTest {

    @Spy
    private Arithm arithm;

    @Test
    void testAddition() {

        int res = arithm.add(2, 5);

        // doReturn(7).when(arithm).add(2, 5);
        assertEquals(res, 7);
    }
}

1

खैर, मेरे मामले में मॉकिटो त्रुटि मुझे whenया wheneverस्टब के बाद वास्तविक विधि को कॉल करने के लिए कह रही थी । चूँकि हम उन परिस्थितियों का आह्वान नहीं कर रहे थे, जिनका हम केवल मखौल उड़ाते थे, मॉकिटो की रिपोर्ट थी कि अनावश्यक स्टब्स या कोड के रूप में।

यह तब है जब त्रुटि आ रही थी:

@Test
fun `should return error when item list is empty for getStockAvailability`() {
    doAnswer(
        Answer<Void> { invocation ->
            val callback =
                invocation.arguments[1] as GetStockApiCallback<StockResultViewState.Idle, StockResultViewState.Error>
            callback.onApiCallError(stockResultViewStateError)
            null
        }
    ).whenever(stockViewModelTest)
        .getStockAvailability(listOf(), getStocksApiCallBack)
}

तब मैंने उस विधि का उल्लेख करने के लिए वास्तविक विधि का उल्लेख किया।

किए गए परिवर्तन नीचे दिए गए हैं stockViewModelTest.getStockAvailability(listOf(), getStocksApiCallBack)

@Test
fun `should return error when item list is empty for getStockAvailability`() {
    doAnswer(
        Answer<Void> { invocation ->
            val callback =
                invocation.arguments[1] as GetStockApiCallback<StockResultViewState.Idle, StockResultViewState.Error>
            callback.onApiCallError(stockResultViewStateError)
            null
        }
    ).whenever(stockViewModelTest)
        .getStockAvailability(listOf(), getStocksApiCallBack)
    //called the actual method here
    stockViewModelTest.getStockAvailability(listOf(), getStocksApiCallBack)
}

अब यह काम कर रहा है।


0

एक बड़ी परियोजना के मामले में, इनमें से प्रत्येक अपवाद को ठीक करना मुश्किल है। उसी समय, उपयोग करने Silentकी सलाह नहीं दी जाती है। मैंने उन सभी अनावश्यक स्टबिंग को हटाने के लिए एक स्क्रिप्ट लिखी है, जिनमें से एक सूची दी गई है।

https://gist.github.com/cueo/da1ca49e92679ac49f808c7ef594e75b

हमें केवल mvnआउटपुट को कॉपी-पेस्ट करना होगा और रेगेक्स का उपयोग करके इन अपवादों की सूची लिखना होगा और स्क्रिप्ट को बाकी का ध्यान रखना चाहिए।


0

यदि आप मॉकिंग करते समय किसी भी () का उपयोग करते हैं, तो आपको @RunWith (MockitoJUnitRunner.Silent .class) के साथ @RunWith (MockitoJUnitRunner.class) रिले करना होगा।


0

जब आप एक मॉक बनाते हैं और उस मॉक का उपयोग नहीं किया जाता है तो इसका उपयोग अप्रयुक्त स्टबिंग अपवाद फेंकता है। आपके मामले में कि नकली वास्तव में नहीं कहा जाता है। इसलिए यह उस त्रुटि को फेंक रहा है। इसलिए, relpace @RunWith(MockitoJUnitRunner.class)साथ @RunWith(MockitoJUnitRunner.Silent.class)जो त्रुटि को दूर करेंगे। यदि आप अभी भी @RunWith(MockitoJUnitRunner.class)अपने तर्क डिबगिंग का उपयोग करना चाहते हैं यदि आपने जिस फ़ंक्शन का मजाक उड़ाया है वह वास्तव में कहा जा रहा है या नहीं।

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