কীভাবে অনাদায়ী স্টুবিং ব্যতিক্রম সমাধান করবেন


108

আমার কোডটি নীচে হিসাবে রয়েছে,

@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)

কীভাবে সমাধান করবেন আমাকে দয়া করে সহায়তা করুন

উত্তর:


119

@RunWith(MockitoJUnitRunner.class)সঙ্গে প্রতিস্থাপন @RunWith(MockitoJUnitRunner.Silent.class)


45
স্বাগত. তারা কেন এই জাতীয় কোডটি প্রতিস্থাপন করবে সে সম্পর্কে আপনার উত্তর আপডেট করা ভাল worth এটি তাদের এবং ভবিষ্যতের দর্শকদের বুঝতে সহায়তা করবে।
বাগগুলি

5
BTW, এটা @RunWith(MockitoJUnitRunner.Silent.class)এবং না নীরব
fgysin পুনর্বহাল মনিকা

6
কোটলিনে:@RunWith(MockitoJUnitRunner.Silent::class)
জুয়ান সরভিয়া

12
নিশ্চিত না কেন এই উত্তরটি কোনও ব্যাখ্যা ছাড়াই উত্সাহ পেতে চলেছে। অন্যান্য উত্তরগুলি আরও অর্থবহ এবং নির্ভুল।
যোগেশ

10
এটি সমস্যার সমাধান করে না, তবে কেবল ত্রুটি বার্তাটি দমন করে এবং ক্লাসের অন্যান্য সমস্ত পরীক্ষাগুলিকে (যদি থাকে তবে) প্রভাব ফেলবে।
ফেন্সার

113

প্রথমে আপনার পরীক্ষার যুক্তি পরীক্ষা করা উচিত। সাধারণত এখানে 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 {
}

4
আমার সেটআপে কঠোরতা সামঞ্জস্য করার সহজ উপায় @ মকিতোসেটিংস (কঠোরতা = কঠোরতা LE এলএনআইএনটি) way ধন্যবাদ!
ম্যাট

7
এই উত্তরটি সম্ভাবনার একটি ভাল ওভারভিউ সরবরাহ করে। যাইহোক, আপনি কেস ভিত্তিতে প্রতি কেস ভিত্তিতে লেন্সিয়েন্ট কঠোরতা সেট করতে পারেন Mockito.lenient().when(...); এই বিশেষ প্রশ্নের জন্য এটি হবেMockito.lenient().when(dao.doSearch(dto)).thenReturn(inspectionsSummaryList);
নেক্সাস

পরীক্ষার শ্রেণিবিন্যাসের সাথে কাজ করার সময় সাবক্লাসে সুপারক্লাস এবং মকিতোসেটেটিংয়ের সাথে এক্সটেনড সংজ্ঞা দিন। আশা করি এটি আমার ব্যয়ের জন্য কারও জন্য সময় সাশ্রয় করবে।
অলৌকিক_ও_ভি

40

নীরবতা কোনও সমাধান নয়। আপনার পরীক্ষায় আপনার মক ঠিক করা দরকার। অফিসিয়াল ডকুমেন্টেশন দেখুন এখানে

অপ্রয়োজনীয় স্টাবগুলি স্ট্যাবড পদ্ধতি কলগুলি যা পরীক্ষার মৃত্যুর সময় কখনও উপলব্ধি করা যায় নি (মকিতোহিন্টও দেখুন), উদাহরণস্বরূপ:

//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
 ...

খেয়াল করুন যে পরীক্ষার সময় কোডের মধ্যে পরীক্ষা করার সময় একটি স্টাবযুক্ত পদ্ধতি কখনই উপলব্ধি করা যায় নি। বিপথগামী স্টাববিং বিকাশকারী, অনুলিপি-অনুলিপি বা পরীক্ষা / কোড বুঝতে না পারার প্রভাব হতে পারে overs যে কোনও উপায়ে, বিকাশকারী অপ্রয়োজনীয় টেস্ট কোড দিয়ে শেষ হয়। কোডবেস পরিষ্কার ও রক্ষণাবেক্ষণের জন্য অপ্রয়োজনীয় কোড অপসারণ করা প্রয়োজন। অন্যথায় পরীক্ষাগুলি পড়ার পক্ষে কঠিন এবং এর কারণ are

অব্যবহৃত stubbings সনাক্তকরণ সম্পর্কে আরও জানতে মকিতোহিন্ট দেখুন।


16
এমন অনেকগুলি পরিস্থিতি রয়েছে যেখানে আপনি অনুরূপ @BeforeEach সেটআপের বিরুদ্ধে 8-9 টি পরীক্ষা লিখেন যেখানে কয়েকটি স্টাফের ব্যবসায়ের যুক্তির কারণে এক স্টাব থেকে ফিরে আসা আইটেমটি অব্যবহৃত থাকে। আপনি (এ) একাধিক পরীক্ষায় বিভক্ত হয়ে কার্যকরভাবে একটি আইটেম বিয়োগ করে বিট copy @পূর্বএক বিভাগটি কপি / পেস্ট করতে পারেন (খ) মকিতো যে use টি পরীক্ষা ব্যবহার করে এবং এটি রয়েছে তার একক লাইন অনুলিপি / পেস্ট করুন না 2 বা (সি) নীরব ব্যবহার না। আমি নীরব / সতর্কতা ব্যবহার করতে পছন্দ করি। এটি কোনও ভাঙ্গা পরীক্ষা নয়।
রকমিটহার্ডপ্লেস

4
@ রকমিটহার্ডপ্লেস, সাইলেন্ট কোনও সমাধান নয় , দ্রুত আপনি কম অনুলিপি / পেস্ট দেখেন তবে আপনার প্রকল্পে নতুন লোক দ্বারা আপনার পরীক্ষা চালিয়ে যাওয়ার সময় এটি সমস্যাযুক্ত হবে। যদি মকিতো বইয়ের দোকান এটি করে যে এটি কোনও কিছুর জন্য নয়।
স্টাফেন গ্রিলন

4
@ এসগ্রিলন: তবে এই সিস্টেমটি মিথ্যা-ধনাত্মক লোডগুলি সনাক্ত করে। এটি, এটি বলে যে কোনও কিছু অব্যবহৃত হয়েছে, তবে এটি স্পষ্টভাবে নয়, কারণ স্টাবটি সরিয়ে ফেলা কার্যকর হয়। এটি এমন নয় যে পরীক্ষার কোডটি উন্নত করা যায় না, এটি হ'ল স্টাবিংয়ের একটি গুরুত্বপূর্ণ রেখাটি কখনই "অপ্রয়োজনীয়" হিসাবে চিহ্নিত করা উচিত নয় । সুতরাং এই চেকটি অক্ষম করতে সক্ষম হওয়ার গুরুত্ব, এটি খুব আগ্রহী।
ক্যারিখন

4
@ ক্যারিখান, যদি আপনার উপহাসটিকে ভুল হিসাবে সনাক্ত করা হয় তবে এটি আপনি যা ভাবেন তা নাও হতে পারে। এটি একটি ত্রুটি থাকতে পারে যখন আপনাকে একটি ঠিক পরীক্ষা দেয়।
স্টাফেন গ্রিলন

@ এসগ্রিলন, দুঃখিত আমি আপনার কাছে আর ফিরে পাইনি। দেখা যাচ্ছে যে এখানে পরীক্ষামূলক মৃত্যুদণ্ডের আদেশের উপর নির্ভর করে এটি "মিথ্যা হিট" তৈরি করতে পারে যেখানে একটি পরীক্ষায় ব্যবহৃত হলেও অন্যটিতে ওভাররাইট করা স্টাবগুলি এটি ট্রিগার করবে। যদিও এটি আমি বলতে পারি এটি দীর্ঘ স্থির।
ক্যারিখন

34

আমার জন্য না এবং @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());

আপনার পরিবর্তে পরীক্ষার কোডটি দেখে নেওয়া উচিত তা বলাই বাহুল্য, তবে আমাদের প্রয়োজনীয় জিনিসগুলি সংকলিত করার এবং পরীক্ষাগুলি সবার আগে চালু করার দরকার ছিল;)


8
আইএমএইচও পুরো পরীক্ষার ক্লাসটি স্থির করে দেওয়ার পরিবর্তে এটি এখানে আমি সবচেয়ে দরকারী উত্তর।
prieshdkr

4
যেহেতু আমি কেবল 1 টি বিদ্রূপ দমন করতে চেয়েছিলাম, এটি আমার পক্ষে সেরা উত্তর। যদিও ওপির পক্ষে সত্যই কোনও উত্তর নয়।
হান্স ওয়াউটারস

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

whenএখানে কিছু করতে আপনার উপহাস কনফিগার করে। যাইহোক, আপনি এই লকের পরে আর কোনও উপায়ে এই মক ব্যবহার করবেন না (একটি করা বাদ দিয়ে verify)। মকিতো আপনাকে সতর্ক করে দিয়েছে যে whenলাইনটি অর্থহীন। সম্ভবত আপনি একটি যুক্তি ত্রুটি করেছেন?


আপনার সহায়তার জন্য ধন্যবাদ
ভিএইচএস

আমার যখন উভয় প্রয়োজন এবং যাচাই করা বিবৃতিগুলি দয়া করে দয়া করে আরও কীভাবে সরানো যায় তার পরামর্শ দিন
ভিএইচএস

4
আপনার পরীক্ষার শ্রেণিতে কোনও ফাংশন কল করুন ( Service) এটি সঠিকভাবে প্রতিক্রিয়া দেখায় কিনা। আপনি মোটেও তা করেন নি, আপনি এখানে কি পরীক্ষা করছেন?
john16384

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

ঠিক আছে, আমার ক্ষেত্রে মকিতো ত্রুটিটি আমাকে স্টাবের পরে 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)
}

এটা এখন কাজ করছে.


1

আপনি যদি এর পরিবর্তে এই স্টাইলটি ব্যবহার করেন:

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

এর সাথে প্রতিস্থাপন করুন:

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

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

প্রতিস্থাপন

@RunWith(MockitoJUnitRunner.class)

সঙ্গে

@RunWith(MockitoJUnitRunner.Silent.class)

বা অপসারণ@RunWith(MockitoJUnitRunner.class)

বা কেবল অযাচিত মশকরা কলগুলি মন্তব্য করুন (অননুমোদিত স্টাব হিসাবে দেখানো হয়েছে)।


0

বড় প্রকল্পের ক্ষেত্রে, এই ব্যতিক্রমগুলির প্রতিটি ঠিক করা কঠিন। একই সময়ে, ব্যবহার করার Silentপরামর্শ দেওয়া হয় না। আমি তাদের একটি তালিকা দিয়ে সমস্ত অপ্রয়োজনীয় stubbings অপসারণ করতে একটি স্ক্রিপ্ট লিখেছি।

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

আমাদের কেবল mvnআউটপুটটি অনুলিপি-পেস্ট করতে হবে এবং রেজিেক্স ব্যবহার করে এই ব্যতিক্রমগুলির তালিকাটি লিখতে হবে এবং স্ক্রিপ্টটিকে বাকীগুলির যত্ন নিতে দেওয়া উচিত।


-1

আপনি যখন কোন মক তৈরি করেন এবং সেই মক ব্যবহার করা হয় না তখন এটি অব্যবহৃত স্টাবিং ব্যতিক্রম ছুঁড়ে দেয়। আপনার ক্ষেত্রে সেই মক আসলে বলা হয় না। সুতরাং এটি যে ত্রুটি নিক্ষেপ করা হয়। তাই, relpace @RunWith(MockitoJUnitRunner.class)সঙ্গে @RunWith(MockitoJUnitRunner.Silent.class)যা ত্রুটি সরিয়ে দেবেন। আপনি যদি এখনও @RunWith(MockitoJUnitRunner.class)তামাশা করেছেন এমন ফাংশনটি আসলে ডাকা হচ্ছে বা না হচ্ছে তবে আপনার যুক্তিটি ডিবাগ করার চেষ্টা করুন।


এটি বিদ্যমান এমন উত্তরগুলিতে আচ্ছাদিত কোনও কিছুই যুক্ত করে না।
ম্যাথু

-3

আপনি ব্যবহার করেন তাহলে কোন () যখন উপহাস, আপনি relpace আছে @RunWith(MockitoJUnitRunner.class)সঙ্গে @RunWith(MockitoJUnitRunner.Silent.class)


এটা সহজ মিথ্যা। any()সঠিকভাবে ব্যবহৃত হলে সাধারণ রানার সাথে পুরোপুরি কাজ করে।
ম্যাথু
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.