মকিতো ম্যাচাররা কীভাবে কাজ করবে?


122

Mockito যুক্তি matchers (যেমন any, argThat, eq, same, এবং ArgumentCaptor.capture()) খুব ভিন্নভাবে Hamcrest matchers থেকে আচরণ।

  • মকিতো ম্যাথারগুলি ঘন ঘন অবৈধ ইউসঅফ ম্যাথার্স এক্সসেপশন সৃষ্টি করে, এমন কোনও কোডেও যে কোনও ম্যাথার ব্যবহারের পরে দীর্ঘায়িত হয়।

  • মকিতো ম্যাথারগুলি অদ্ভুত নিয়মগুলির দিকে তাকাচ্ছে যেমন একটি প্রদত্ত পদ্ধতিতে যদি একটি যুক্তি ম্যাচার ব্যবহার করে তবে কেবলমাত্র সমস্ত আর্গুমেন্টের জন্য মকিতো ম্যাথার ব্যবহার প্রয়োজন।

  • ওভাররাইড করার Answerসময় বা যখন ব্যবহার করার সময় মকিতো ম্যাথারগুলি নলপয়েন্টারএক্সসেপশন সৃষ্টি করতে পারে (Integer) any()etc.

  • নির্দিষ্ট উপায়ে মকিতো ম্যাথারদের সাথে সংশোধনকারী কোড ব্যতিক্রম এবং অপ্রত্যাশিত আচরণ তৈরি করতে পারে এবং পুরোপুরি ব্যর্থ হতে পারে।

মকিতো ম্যাচারগুলি কেন এইভাবে ডিজাইন করা হয়েছে এবং সেগুলি কীভাবে বাস্তবায়ন করা হয়?

উত্তর:


236

Mockito matchers স্ট্যাটিক পদ্ধতি এবং সেই পদ্ধতি, যা কল হয় আর্গুমেন্ট জন্য দাঁড়ানো কল সময় whenএবং verify

হ্যামক্রেস্ট ম্যাথারস (আর্কাইভ সংস্করণ) (বা হ্যামক্রেস্ট-স্টাইলের ম্যাথারস) রাষ্ট্রবিহীন, সাধারণ-উদ্দেশ্য বস্তুর উদাহরণস্বরূপ যে Matcher<T>কোনও পদ্ধতি কার্যকর করে এবং প্রকাশ করে matches(T)যে বস্তু ম্যাচারের মানদণ্ডের সাথে মেলে যদি সত্য ফিরে আসে returns এগুলি পার্শ্ব প্রতিক্রিয়া মুক্ত থাকার উদ্দেশ্যে করা হয় এবং সাধারণত নীচের মত জোর হিসাবে ব্যবহৃত হয়।

/* Mockito */  verify(foo).setPowerLevel(gt(9000));
/* Hamcrest */ assertThat(foo.getPowerLevel(), is(greaterThan(9000)));

মকিতো ম্যাথারস উপস্থিত রয়েছে, হামক্রস্ট-স্টাইলের ম্যাথার থেকে পৃথক, যাতে মিলের অভিব্যক্তিগুলির বিবরণগুলি সরাসরি পদ্ধতি আমন্ত্রণের সাথে ফিট করে : মকিতো ম্যাচারগুলি ফিরে আসে Tযেখানে হ্যামরেস্ট ম্যাচার পদ্ধতিগুলি ম্যাচার অবজেক্টগুলি (টাইপের Matcher<T>) প্রত্যাবর্তন করে ।

Mockito matchers যেমন স্ট্যাটিক পদ্ধতিগুলির মাধ্যমে প্রার্থনা করছে eq, any, gt, এবং startsWithউপর org.mockito.Matchersএবং org.mockito.AdditionalMatchers। এছাড়াও অ্যাডাপ্টারগুলি রয়েছে, যা মকিতো সংস্করণগুলিতে পরিবর্তিত হয়েছে:

  • মকিতো ১.x এর জন্য Matchersকিছু কল রয়েছে (যেমন intThatবা argThat) হ'ল মকিতো ম্যাথাররা যা হ্যামক্রস্ট ম্যাথারগুলিকে প্যারামিটার হিসাবে সরাসরি গ্রহণ করে। ArgumentMatcher<T>প্রসারিত org.hamcrest.Matcher<T>, যা অভ্যন্তরীণ হামক্রস্টের উপস্থাপনায় ব্যবহৃত হয়েছিল এবং এটি কোনও প্রকার মকিতো ম্যাচারের পরিবর্তে হামক্রস্ট ম্যাচারের বেস ক্লাস ছিল ।
  • মকিতো ২.০+ এর জন্য, মকিতোর আর হ্যামকারেস্টের উপর সরাসরি নির্ভরতা নেই। Matchersরিং phrased intThatবা argThatমোড়ানো ArgumentMatcher<T>যে বস্তু আর বাস্তবায়ন org.hamcrest.Matcher<T>কিন্তু অনুরূপ উপায়ে ব্যবহার করা হয়। হামক্রস্ট অ্যাডাপ্টার যেমন argThatএবং intThatএখনও পাওয়া যায়, তবে MockitoHamcrestপরিবর্তে চলে গেছে ।

ম্যাচাররা হ্যামক্রেস্ট বা কেবল হ্যামক্রস্ট-স্টাইলই হোক না কেন, সেগুলি এ জাতীয়ভাবে মানিয়ে নেওয়া যায়:

/* Mockito matcher intThat adapting Hamcrest-style matcher is(greaterThan(...)) */
verify(foo).setPowerLevel(intThat(is(greaterThan(9000))));

উপরের বিবৃতিতে: foo.setPowerLevelএকটি পদ্ধতি যা গ্রহণ করে intis(greaterThan(9000))একটি প্রদান করে Matcher<Integer>, যা setPowerLevelআর্গুমেন্ট হিসাবে কাজ করবে না । intThatমকিতো ম্যাচার মোড়কে দেয় যে হামক্রস্ট-স্টাইলের ম্যাচার এবং একটি ফেরত দেয় intযাতে এটি যুক্তি হিসাবে উপস্থিত হতে পারে; মকিতো ম্যাচাররা gt(9000)উদাহরণস্বরূপ কোডের প্রথম লাইনের মতো সেই সম্পূর্ণ এক্সপ্রেশনটিকে একটি একক কলে মুড়িয়ে দেবে।

ম্যাথাররা কী করে / ফেরত দেয়

when(foo.quux(3, 5)).thenReturn(true);

যুক্তি ম্যাথারগুলি ব্যবহার না করার সময়, মকিতো আপনার যুক্তির মানগুলি রেকর্ড করে এবং তাদের equalsপদ্ধতিগুলির সাথে তাদের তুলনা করে ।

when(foo.quux(eq(3), eq(5))).thenReturn(true);    // same as above
when(foo.quux(anyInt(), gt(5))).thenReturn(true); // this one's different

আপনি যখন ম্যাচারকে এর মতো anyবা gt(এর চেয়ে বড়) কল করেন, মকিতো এমন ম্যাচারকারী বস্তু সঞ্চয় করে যা মকিতো সেই সমতা পরীক্ষাটি এড়িয়ে যায় এবং আপনার পছন্দের ম্যাচটি প্রয়োগ করে। argumentCaptor.capture()এটির ক্ষেত্রে একটি ম্যাচার সংরক্ষণ করে যা পরে তদন্তের পরিবর্তে তার যুক্তিটি সংরক্ষণ করে।

ম্যাচার্স শূন্য, খালি সংগ্রহ বা ডামি মানগুলি ফিরিয়ে দেয় null। Mockito জন্য 0 মত একটি নিরাপদ, উপযুক্ত ডামি মান ফেরত পাঠাতে, চেষ্টা করে anyInt()বা any(Integer.class)অথবা একটি খালি List<String>জন্য anyListOf(String.class)। টাইপ ইরেজরের কারণে, যদিও, মকিতোতে কোনও মান ফেরত দেওয়ার জন্য টাইপের তথ্যের অভাব রয়েছে বা এর nullজন্য any()বা argThat(...), যা একটি nullআদিম মান "অটো-আনবক্স" করার চেষ্টা করলে নলপয়েন্টারএক্সসেপশন ঘটাতে পারে।

ম্যাচাররা প্যারামিটারের মানগুলি পছন্দ করে eqএবং gtনেয়; আদর্শভাবে, স্টাবিং / যাচাইকরণ শুরু হওয়ার আগে এই মানগুলি গণনা করা উচিত। বিদ্রূপের মাঝামাঝি সময়ে অন্য কলটি কল করা স্টাবের সাথে হস্তক্ষেপ করতে পারে।

ম্যাচের পদ্ধতিগুলি রিটার্ন মান হিসাবে ব্যবহার করা যায় না; উদাহরণস্বরূপ বাক্যাংশ thenReturn(anyInt())বা thenReturn(any(Foo.class))মকিতোতে কোনও উপায় নেই । স্টিবিং কলগুলিতে কোন উদাহরণটি ফিরে আসবে তা অবশ্যই মকিতোকে জানতে হবে এবং আপনার জন্য নির্বিচারে রিটার্ন মান চয়ন করবে না।

বাস্তবায়ন বিশদ

ম্যাচারস আর্গুমেন্টম্যাচারস্টোরেজ নামে একটি ক্লাসে থাকা একটি স্ট্যাকে (হামক্রস্ট-স্টাইলের অবজেক্ট ম্যাচচার হিসাবে) সংরক্ষণ করা হয় । MockitoCore এবং Matchers প্রতিটি নিজের একটি ThreadSafeMockingProgress উদাহরণস্বরূপ, যা স্ট্যাটিক্যালি একটি ThreadLocal হোল্ডিং MockingProgress দৃষ্টান্ত রয়েছে। এটি এই মকিংপ্রোগ্রেস ইমপল যা একটি কংক্রিট আর্গুমেন্টম্যাচারস্টোরেজআইপল ধারণ করে । ফলস্বরূপ, মোক এবং ম্যাচার অবস্থা স্থিতিশীল তবে মকিতো এবং ম্যাচার্স শ্রেণীর মধ্যে ধারাবাহিকভাবে থ্রেড-স্কোপড।

সর্বাধিক মিলকারীর কল শুধুমাত্র মত matchers জন্য একটি ব্যতিক্রম সঙ্গে, এই স্ট্যাকের যোগ and, orএবংnot । এটি পুরোপুরি জাওয়ার মূল্যায়ন আদেশের সাথে (এবং এর উপর নির্ভর করে) যা কোনও পদ্ধতিতে বলার আগে বাম থেকে ডান যুক্তির মূল্যায়ন করে:

when(foo.quux(anyInt(), and(gt(10), lt(20)))).thenReturn(true);
[6]      [5]  [1]       [4] [2]     [3]

এটা হবে:

  1. anyInt()স্ট্যাক যোগ করুন ।
  2. gt(10)স্ট্যাক যোগ করুন ।
  3. lt(20)স্ট্যাক যোগ করুন ।
  4. সরান gt(10)এবং lt(20)যোগ করুন and(gt(10), lt(20))
  5. কল করুন foo.quux(0, 0), যা (অন্যথায় স্টাব না করা হলে) ডিফল্ট মানটি দেয় false। অভ্যন্তরীণভাবে মকিতো quux(int, int)সবচেয়ে সাম্প্রতিক কল হিসাবে চিহ্নিত করেছে ।
  6. কল when(false), যা তার যুক্তিটি বাতিল করে এবং quux(int, int)5 টিতে চিহ্নিত স্টাব পদ্ধতিটি প্রস্তুত করে: কেবলমাত্র দুটি বৈধ রাষ্ট্র স্ট্যাকের দৈর্ঘ্য 0 (সমতা) বা 2 (ম্যাথার) সহ এবং স্ট্যাকের দুটি পদক্ষেপ রয়েছে (পদক্ষেপ 1 এবং 4), সুতরাং মকিতো any()তার প্রথম তর্ক এবং and(gt(10), lt(20))দ্বিতীয় তর্কটির জন্য ম্যাচারের সাথে পদ্ধতিটি স্টাব করে এবং স্ট্যাকটি সাফ করে।

এটি কয়েকটি বিধি প্রদর্শন করে:

  • মকিতো quux(anyInt(), 0)এবং এর মধ্যে পার্থক্য বলতে পারে না quux(0, anyInt())। তারা উভয় quux(0, 0)স্ট্যাকের উপর একটি আন্ত ম্যাচারের সাথে কল করার মতো দেখায় । ফলস্বরূপ, আপনি যদি একটি ম্যাচার ব্যবহার করেন তবে আপনাকে সমস্ত যুক্তি মেলাতে হবে।

  • কল অর্ডার কেবল গুরুত্বপূর্ণ নয়, এটি এটিকে সমস্ত কাজ করে । ভেরিয়েবলগুলিতে ম্যাথারগুলি সরানো সাধারণত কাজ করে না, কারণ এটি সাধারণত কল ক্রম পরিবর্তন করে। পদ্ধতিগুলিতে ম্যাথারগুলি এক্সট্র্যাক্ট করা দুর্দান্ত কাজ করে।

    int between10And20 = and(gt(10), lt(20));
    /* BAD */ when(foo.quux(anyInt(), between10And20)).thenReturn(true);
    // Mockito sees the stack as the opposite: and(gt(10), lt(20)), anyInt().
    
    public static int anyIntBetween10And20() { return and(gt(10), lt(20)); }
    /* OK */  when(foo.quux(anyInt(), anyIntBetween10And20())).thenReturn(true);
    // The helper method calls the matcher methods in the right order.
  • স্ট্যাকটি প্রায়শই যথেষ্ট পরিবর্তিত হয় যে মকিতো খুব সাবধানতার সাথে এটি পুলিশ করতে পারে না। এটি যখন আপনি মকিতো বা একটি উপহাসের সাথে ইন্টারঅ্যাক্ট করেন তখন এটি স্ট্যাকটি পরীক্ষা করতে পারে এবং অবিলম্বে ব্যবহৃত হয় বা দুর্ঘটনাক্রমে পরিত্যক্ত হয় কিনা তা জেনেও ম্যাচারদের গ্রহণ করতে হবে। তাত্ত্বিকভাবে, স্ট্যাকটি কল করার whenবা তার বাইরে সর্বদা খালি থাকা উচিত verify, তবে মকিতো স্বয়ংক্রিয়ভাবে তা পরীক্ষা করতে পারে না। আপনি নিজে দিয়ে চেক করতে পারেন Mockito.validateMockitoUsage()

  • কলটিতে when, মকিতো আসলে সেই পদ্ধতিটিকে প্রশ্নবিদ্ধভাবে কল করে, যা যদি আপনি ব্যতিক্রম ছুঁড়ে দেওয়ার জন্য পদ্ধতিটি স্টাড করে থাকেন (বা শূন্যের বা অ-নাল মানগুলির প্রয়োজন হয়) তবে এটি ব্যতিক্রম করবে। doReturnএবং doAnswer(ইত্যাদি) না না প্রকৃত পদ্ধতি ডাকা এবং প্রায়ই একটি দরকারী বিকল্প হয়।

  • আপনি stubbing মাঝখানে একটি উপহাস পদ্ধতি বলা হত (যেমন একটি জন্য একটি উত্তর নিরূপণ করা eqমিলকারীর), Mockito বিরুদ্ধে স্ট্যাক দৈর্ঘ্য চেক করবে যে পরিবর্তে কল, এবং সম্ভবত ব্যর্থ হয়।

  • আপনি যদি চূড়ান্ত পদ্ধতিতে স্টাবিং / যাচাইয়ের মতো খারাপ কিছু করার চেষ্টা করেন তবে মকিতো আসল পদ্ধতিটি কল করবে এবং স্ট্যাকের উপরে অতিরিক্ত ম্যাচারও রেখে যাবেfinalপদ্ধতি কল একটি ব্যতিক্রম নিক্ষেপ নাও করতে পারে, কিন্তু আপনি এমন একটি পেতে পারেন InvalidUseOfMatchersException বিপথগামী matchers একটি উপহাস সঙ্গে যখন আপনি পরবর্তি ইন্টারঅ্যাক্ট থেকে।

সাধারন সমস্যা

  • অবৈধ ইউসঅফ ম্যাথার্স এক্সসেপশন :

    • যদি আপনি মোটেই ম্যাচার ব্যবহার করেন এবং আপনি যে কোনও whenবা verifyকলটির বাইরে কোনও ম্যাচার ব্যবহার করেন নি তা প্রতিটি যুক্তিতে ঠিক একটি ম্যাথার কল রয়েছে কিনা তা পরীক্ষা করে দেখুন । ম্যাচারদের কখনই স্টাবড রিটার্ন মান বা ক্ষেত্র / ভেরিয়েবল হিসাবে ব্যবহার করা উচিত নয়।

    • ম্যাচারের যুক্তি সরবরাহ করার অংশ হিসাবে আপনি কোন উপহাসকে কল করছেন না তা পরীক্ষা করুন।

    • আপনি কোনও ম্যাচারের সাথে চূড়ান্ত পদ্ধতিটি স্তম্ভিত / যাচাই করার চেষ্টা করছেন না তা পরীক্ষা করুন। স্ট্যাকের উপর ম্যাচার রেখে যাওয়ার এক দুর্দান্ত উপায় এবং যদি আপনার চূড়ান্ত পদ্ধতিটি ব্যতিক্রম না ছড়িয়ে দেয় তবে আপনি কেবল যে পদ্ধতিটি উপহাস করছেন তা চূড়ান্ত হওয়ার বিষয়টি আপনি কেবলমাত্র বুঝতে পারবেন।

  • আদিম আর্গুমেন্টের সাথে নালপয়েন্টারএক্সেপশন: 0 টি (Integer) any()শূন্য করার সময় শূন্য any(Integer.class)দেয়; NullPointerExceptionআপনি যদি intএকটি পূর্ণসংখ্যার পরিবর্তে এর চেয়ে প্রত্যাশা করছেন তবে এটির কারণ হতে পারে । যাই হোক না কেন, পছন্দ করুন anyInt(), যা শূন্য ফিরে আসবে এবং অটো-বক্সিং পদক্ষেপও এড়িয়ে যাবে।

  • নালপয়েন্টারএক্সেপশন বা অন্যান্য ব্যতিক্রম: কল করার জন্য when(foo.bar(any())).thenReturn(baz)আসলে কল হবে foo.bar(null), যা নাল যুক্তি পাওয়ার সময় আপনি কোনও ব্যতিক্রম ছুঁড়ে মারতে পারেন ub স্যুইচ করা doReturn(baz).when(foo).bar(any()) ছেড়ে যাওয়া stubbed আচরণ

সাধারণ সমস্যা সমাধান

  • মকিটোজেউইনিটরুনার ব্যবহার করুন , বা validateMockitoUsageআপনার tearDownবা @Afterপদ্ধতিতে স্পষ্টভাবে কল করুন (যা রানার স্বয়ংক্রিয়ভাবে আপনার জন্য করবে)। আপনি ম্যাচারদের অপব্যবহার করেছেন কিনা তা এটি নির্ধারণে সহায়তা করবে।

  • ডিবাগিংয়ের উদ্দেশ্যে, validateMockitoUsageআপনার কোডটিতে সরাসরি কলগুলি যুক্ত করুন । আপনার যদি স্ট্যাকের কিছু থাকে তবে এটি ফেলে দেবে, যা খারাপ লক্ষণের একটি ভাল সতর্কতা।


2
এই লেখার জন্য ধন্যবাদ। যখন / ততবার রিটার্ন ফর্ম্যাটটি আমাকে ডু রিটারনে / কখন পরিবর্তন না করা পর্যন্ত একটি নালপয়েন্টার এক্সেপশন problems
yngwietiger

11

জেফ বোম্যানের দুর্দান্ত উত্তরের একটি সামান্য সংযোজন, যেমন আমার নিজের সমস্যার কোনও সমাধানের জন্য অনুসন্ধান করার সময় আমি এই প্রশ্নটি পেয়েছি:

যদি কোনও পদ্ধতির কাছে কল একাধিক মক এর whenপ্রশিক্ষিত কলগুলির সাথে মিলে যায় তবে whenকলগুলির ক্রমটি গুরুত্বপূর্ণ, এবং সবচেয়ে প্রশস্ত থেকে সুনির্দিষ্ট হওয়া উচিত। জেফের একটি উদাহরণ থেকে শুরু করে:

when(foo.quux(anyInt(), anyInt())).thenReturn(true);
when(foo.quux(anyInt(), eq(5))).thenReturn(false);

আদেশটি যা (সম্ভবত) পছন্দসই ফলাফলটি নিশ্চিত করে:

foo.quux(3 /*any int*/, 8 /*any other int than 5*/) //returns true
foo.quux(2 /*any int*/, 5) //returns false

যদি আপনি কখন কলগুলি উল্টো করেন তবে ফলাফলটি সর্বদা পাওয়া যায় true


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

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