মকিতো: পদ্ধতিতে গুপ্তচরবৃত্তি করার চেষ্টা করা হচ্ছে মূল পদ্ধতিটিকে কল করা


349

আমি মকিতো 1.9.0 ব্যবহার করছি। আমি JUnit পরীক্ষায় কোনও শ্রেণির একক পদ্ধতির আচরণের উপহাস করতে চাই, তাই আমারও রয়েছে

final MyClass myClassSpy = Mockito.spy(myInstance);
Mockito.when(myClassSpy.method1()).thenReturn(myResults);

সমস্যাটি হচ্ছে, দ্বিতীয় লাইনে myClassSpy.method1()আসলে ডাকা হচ্ছে, যার ব্যতিক্রম ঘটে exception আমি মকগুলি ব্যবহার করার একমাত্র কারণ হ'ল পরে, যখনই myClassSpy.method1()ডাকা হবে তখন আসল পদ্ধতিটি কল করা হবে না এবং myResultsঅবজেক্টটি ফিরে আসবে।

MyClassএটি একটি ইন্টারফেস এবং myInstanceএটি বাস্তবায়ন, যদি এটি গুরুত্বপূর্ণ।

গুপ্তচরবৃত্তির এই আচরণটি সংশোধন করতে আমার কী করা দরকার?


: এই দেখে নিন stackoverflow.com/a/29394497/355438
Lu55

উত্তর:


608

আমাকে অফিসিয়াল ডকুমেন্টেশন উদ্ধৃত করুন :

বাস্তব বস্তুর গুপ্তচরবৃত্তির উপর গুরুত্বপূর্ণ গ্যাঁচা!

কখনও কখনও স্টাইবিং স্পেসের জন্য কখন (অবজেক্ট) ব্যবহার করা অসম্ভব। উদাহরণ:

List list = new LinkedList();
List spy = spy(list);

// Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
when(spy.get(0)).thenReturn("foo");

// You have to use doReturn() for stubbing
doReturn("foo").when(spy).get(0);

আপনার ক্ষেত্রে এটি কিছু যায়:

doReturn(resulstIWant).when(myClassSpy).method1();

26
আমি যদি এই পদ্ধতিটি ব্যবহার করি এবং আমার আসলটি তখনও কল হয়ে যায়? আমি যে পরামিতিগুলি দিয়েছি তাতে কি সমস্যা হতে পারে? এখানে পুরো পরীক্ষাটি দেওয়া হয়েছে: পেস্টবিন.com / জাইওয়াই 790 পিsend পদ্ধতিটি বলা হচ্ছে
এভেজেনি পেট্রভ

25
আপনার মূল পদ্ধতিটি চূড়ান্ত হওয়ার কারণে সম্ভবত এখনও যদি আপনার মূল পদ্ধতিটি বলা হয় তবে @ ইভজেনিপেট্রভকে বলা যেতে পারে। মকিতো চূড়ান্ত পদ্ধতিগুলি উপহাস করে না এবং চূড়ান্ত পদ্ধতিগুলির উপহাস সম্পর্কে আপনাকে সতর্ক করতে পারে না।
মার্চজি

1
এটি কি ডট্রো () এর পক্ষেও সম্ভব?
গব্লিন্স

1
হ্যাঁ, দুর্ভাগ্যক্রমে স্থির পদ্ধতিগুলি আনম্যাক এবং "আন-স্পাই-সক্ষম"। স্থিতিশীল পদ্ধতিগুলির সাথে মোকাবিলা করার জন্য আমি যা করি তা হ'ল স্থির কলের চারপাশে কোনও পদ্ধতি মোড়ানো এবং সেই পদ্ধতিতে একটি ডনথিং বা ডর রিটার্ন ব্যবহার করা। সিঙ্গলেটন বা স্কেল অবজেক্টের সাহায্যে আমি যুক্তির মাংসটিকে একটি বিমূর্ত শ্রেণিতে স্থানান্তরিত করি এবং এটি আমাকে একটি গুপ্তচর তৈরি করতে পারে এমন অবজেক্টটির একটি বিকল্প পরীক্ষার ক্লাস ইমপ্ল করার ক্ষমতা দেয়।
অ্যান্ড্রু নরম্যান

24
এবং যদি না চূড়ান্ত এবং না স্থির পদ্ধতিটি এখনও কল হচ্ছে?
এক্স-হুমান

27

আমার ক্ষেত্রে গৃহীত উত্তর থেকে পৃথক ছিল। আমি সেই প্যাকেজে বাস না করে এমন একটি উদাহরণের জন্য একটি প্যাকেজ-ব্যক্তিগত পদ্ধতি উপহাস করার চেষ্টা করছিলাম

package common;

public class Animal {
  void packageProtected();
}

package instances;

class Dog extends Animal { }

এবং পরীক্ষা ক্লাস

package common;

public abstract class AnimalTest<T extends Animal> {
  @Before
  setup(){
    doNothing().when(getInstance()).packageProtected();
  }

  abstract T getInstance();
}

package instances;

class DogTest extends AnimalTest<Dog> {
  Dog getInstance(){
    return spy(new Dog());
  }

  @Test
  public void myTest(){}
}

সংকলনটি সঠিক, তবে যখন এটি পরীক্ষাটি সেটআপ করার চেষ্টা করে, এটি পরিবর্তে আসল পদ্ধতিটি শুরু করে।

পদ্ধতিটি সুরক্ষিত বা জনসাধারণের দ্বারা সমাধানের বিষয়টি সমস্যা সমাধান করে, এটি কোনও পরিষ্কার সমাধান নয়।


2
আমি অনুরূপ ইস্যুতে দৌড়েছি, তবে পরীক্ষা এবং প্যাকেজ-ব্যক্তিগত পদ্ধতি একই প্যাকেজে ছিল। আমি মনে করি সম্ভবত মকিতোর সাধারণভাবে প্যাকেজ-প্রাইভেট পদ্ধতিতে সমস্যা রয়েছে।
ডেভ

22

আমার ক্ষেত্রে, মকিতো ২.০ ব্যবহার করে, আসল কলটি আটকে রাখতে আমাকে সমস্ত any()পরামিতি পরিবর্তন করতে nullable()হয়েছিল।


2
শীর্ষস্থানীয় উত্তরটি আপনার নিচে নামতে দেবেন না, এটি আমার সমস্যার সমাধান করেছে :) আমি কয়েক ঘন্টা ধরে এটির সাথে লড়াই করে যাচ্ছি!
ক্রিস ক্যাসেল

3
এটা আমার জন্য উত্তর ছিল। আপনার পদ্ধতিটিকে বিদ্রূপ করার সময় যারা অনুসরণ করে তাদের পক্ষে আরও সহজ করার জন্য বাক্য foo = Mockito.spy(foo); Mockito.doReturn(someValue).when(foo).methodToPrevent(nullable(ArgumentType.class));
গঠনটি

মকিতো ২.২৩.৪ সহ আমি নিশ্চিত করতে পারি যে এটি প্রয়োজনীয় নয়, এটি কাজ করে anyএবং eqম্যাচচারগুলি দিয়ে fine
vmaldosan

2
২.২৩.৪ লিবি সংস্করণে তিনটি পৃথক পদ্ধতির চেষ্টা করা হয়েছে: যে কোনও (), একা () এবং নলযোগ্য ()। কেবল পরে কাজ করা হয়েছে
ryzhman

হাই, আপনার সমাধানটি সত্যিই দুর্দান্ত এবং আমার পক্ষেও কাজ করেছে। ধন্যবাদ
ধীরেন সোলঙ্কি

16

টমাসজ নুরকিউইচের উত্তরটি পুরো গল্পটি না বলে দেখা যাচ্ছে!

এনবি মকিতো সংস্করণ: 1.10.19।

আমি অনেকটা মকিতো নবাগত, সুতরাং নিম্নলিখিত আচরণটি ব্যাখ্যা করতে পারি না: যদি এই উত্তরটির উন্নতি করতে পারে এমন কোনও বিশেষজ্ঞের বাইরে থাকেন তবে দয়া করে নির্দ্বিধায় অনুভব করুন।

এখানে প্রশ্নে পদ্ধতিটি getContentStringValue, নয় final এবং নয় static

এই লাইন করে মূল পদ্ধতি কল getContentStringValue:

doReturn( "dummy" ).when( im ).getContentStringValue( anyInt(), isA( ScoreDoc.class ));

এই লাইনটি মূল পদ্ধতিটিকে কল করে নাgetContentStringValue :

doReturn( "dummy" ).when( im ).getContentStringValue( anyInt(), any( ScoreDoc.class ));

যে কারণে আমি উত্তর দিতে পারছি না, isA()উদ্দেশ্যে উদ্দেশ্যমূলক (?) "পদ্ধতিটি কল করবেন না" ব্যবহারটি doReturnব্যর্থ হওয়ার কারণ ঘটায় ।

আসুন এখানে জড়িত পদ্ধতি স্বাক্ষরগুলি দেখুন: এগুলি উভয়েরই staticপদ্ধতি Matchers। উভয়কেই জাভাদোক ফিরে আসার কথা বলেছিলেন null, যা আপনার নিজের মাথা নিজেই পাওয়া কিছুটা কঠিন। সম্ভবত Classপরামিতি হিসাবে অবজেক্টটি পাস করা হয় তবে পরীক্ষা হয় তবে ফলাফল কখনই গণনা করা হয় না বা বাতিল হয় না। প্রদত্ত যে nullকোন ক্লাসের জন্য স্ট্যান্ড করতে পারবেন এবং আপনি বলা হবে না ব্যঙ্গ পদ্ধতি জন্য প্রত্যাশী হয়, পারে স্বাক্ষর যে isA( ... )এবং any( ... )ঠিক ফিরে nullএকটি জেনেরিক প্যারামিটার বদলে * <T>?

যাই হোক:

public static <T> T isA(java.lang.Class<T> clazz)

public static <T> T any(java.lang.Class<T> clazz)

এপিআই ডকুমেন্টেশন এ সম্পর্কে কোনও ক্লু দেয় না। এটি বলে মনে হয় যে এই ধরনের "পদ্ধতিটিকে কল করবেন না" আচরণের প্রয়োজন "খুব বিরল"। ব্যক্তিগতভাবে আমি এই কৌশলটি সর্বদা ব্যবহার করি : সাধারণত আমি দেখতে পাই যে উপহাসের মধ্যে কয়েকটি লাইন জড়িত থাকে যা "দৃশ্য সেট করে" ... তারপরে এমন কোনও পদ্ধতি কল করে যার পরে মক প্রসঙ্গে আপনি দৃশ্যের বাইরে চলে যান ... ... এবং আপনি দৃশ্যাবলী এবং প্রপস স্থাপন করার সময় আপনি যা চান সর্বশেষ জিনিসটি হ'ল অভিনেতাদের মঞ্চে বাম দিকে প্রবেশ করা এবং তাদের হৃদয়কে অভিনয় করা শুরু করা ...

তবে এটি আমার বেতন গ্রেডের বাইরে ... আমি যে কোনও পাসকারী মকিতো উচ্চ পুরোহিতের কাছ থেকে ব্যাখ্যাগুলি আমন্ত্রণ জানাচ্ছি ...

* "জেনেরিক প্যারামিটার" কি সঠিক শব্দ?


আমি জানি না যে এটি স্পষ্টতা যোগ করে বা বিষয়টি আরও বিভ্রান্ত করে কিনা, তবে আইএএ () এবং যে কোনও () এর মধ্যে পার্থক্যটি এটি আসলে টাইপ চেকিং করে না, অন্যদিকে পদ্ধতিগুলির কোনও () পরিবার কেবল টাইপ কাস্টিং এড়ানোর জন্য তৈরি করা হয়েছিল the যুক্তি.
কেভিন ওয়েলকার

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

1
ইতিহাস হ'ল যে কোনও এক্সএক্স পদ্ধতিগুলি কেবল টাইপকাস্টিংয়ের সাথে মোকাবিলা করার উপায় হিসাবে তৈরি হয়েছিল। তারপরে যখন তাদের প্রস্তাব দেওয়া হয়েছিল যে তারা যুক্তি যাচাই করে যুক্ত করুন, তারা বিদ্যমান এপিআইর ব্যবহারকারীদের ভাঙতে চায় না, তাই তারা ইসএ () পরিবার তৈরি করেছে। যে কোনও () পদ্ধতিতে সমস্ত ধরণের পরীক্ষা করা উচিত ছিল, তা জেনেও তারা মকিতো ২ এক্স এক্স ওভারহল (যা আমি এখনও চেষ্টা করি নি) এর মধ্যে অন্যান্য ব্রেকিং পরিবর্তন না হওয়া পর্যন্ত সেগুলি পরিবর্তন করতে বিলম্ব করেছিল। ২.x + এ, যে কোনও এক্স () পদ্ধতিগুলি আইএসএ () পদ্ধতির জন্য উপকরণ।
কেভিন ওয়েলকার

ধন্যবাদ. এটি আমাদের মধ্যে যারা একই সাথে বেশ কয়েকটি গ্রন্থাগার আপডেট করে থাকে তাদের জন্য একটি গুরুত্বপূর্ণ উত্তর, কারণ যে কোডটি চালানো হত তা হঠাৎ এবং নিঃশব্দে ব্যর্থ হয়।
ডেক্স স্ট্যাকার

5

গুপ্তচরবৃত্তির সাথে সমস্যার সৃষ্টি হতে পারে এমন আরও একটি সম্ভাব্য পরিস্থিতি হ'ল আপনি যখন বসন্তের মটরশুটি পরীক্ষা করছেন (স্প্রিং টেস্ট ফ্রেমওয়ার্ক সহ) বা পরীক্ষার সময় আপনার অবজেক্টগুলিকে প্রক্সিং করছে এমন কোনও অন্য কাঠামো

উদাহরণ

@Autowired
private MonitoringDocumentsRepository repository

void test(){
    repository = Mockito.spy(repository)
    Mockito.doReturn(docs1, docs2)
            .when(repository).findMonitoringDocuments(Mockito.nullable(MonitoringDocumentSearchRequest.class));
}

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

repository = MonitoringDocumentsRepository$$EnhancerBySpringCGLIB$$MockitoMock$

@ এসপিস বিউন উদ্ধার

পরিবর্তে যদি @Autowiredটীকাগুলি আমরা টীকাগুলি ব্যবহার করি @SpyBean, আমরা উপরের সমস্যাটি সমাধান করব, স্পাইবিয়ান টিকাটি সংগ্রহস্থল অবজেক্টটিও ইনজেক্ট করবে তবে এটি প্রথমে মকিতো দ্বারা প্রক্সড হবে এবং এটি ভিতরে ডিবাগারটির মতো দেখতে পাবেন

repository = MonitoringDocumentsRepository$$MockitoMock$$EnhancerBySpringCGLIB$

এবং কোডটি এখানে:

@SpyBean
private MonitoringDocumentsRepository repository

void test(){
    Mockito.doReturn(docs1, docs2)
            .when(repository).findMonitoringDocuments(Mockito.nullable(MonitoringDocumentSearchRequest.class));
}

1

আমি আসল পদ্ধতিটি কল করার জন্য স্পাইয়ের আরও একটি কারণ খুঁজে পেয়েছি।

কারও ধারনা ছিল একটি finalশ্রেণি উপহাস করার জন্য , এবং এটি সম্পর্কে পাওয়া গেছে MockMaker:

যেহেতু এটি আমাদের বর্তমান ব্যবস্থায় আলাদাভাবে কাজ করে এবং এর একটির বিভিন্ন সীমাবদ্ধতা রয়েছে এবং আমরা অভিজ্ঞতা এবং ব্যবহারকারীর প্রতিক্রিয়া সংগ্রহ করতে চাইলে এই বৈশিষ্ট্যটি স্পষ্টভাবে সক্রিয় করতে হবে; এটি src/test/resources/mockito-extensions/org.mockito.plugins.MockMakerএকক লাইনযুক্ত ফাইল তৈরি করে মকিটো এক্সটেনশন প্রক্রিয়াটির মাধ্যমে করা যেতে পারে :mock-maker-inline

সূত্র: https://github.com/mockito/mockito/wiki/What%27s-new-in-Mockito-2#mock-the-unmockable-opt-in-mocking-of-final-classmethods

আমি একীভূত হয়ে ফাইলটি আমার মেশিনে নিয়ে আসার পরে, আমার পরীক্ষাগুলি ব্যর্থ হয়েছিল।

আমাকে কেবল লাইনটি (বা ফাইল) সরিয়ে ফেলতে হয়েছিল, এবং spy()কাজ করেছে।


এটি আমার ক্ষেত্রে কারণ ছিল, আমি একটি চূড়ান্ত পদ্ধতি উপহাস করার চেষ্টা করছিলাম তবে এটি একটি বিচ্ছিন্ন বার্তা ছাড়াই আসলটিকে কল করে চলেছিল যা বিভ্রান্তিকর ছিল।
বাশার আলী লাবাদী

1

পার্টিতে দেরিতে হলেও উপরে সমাধানগুলি আমার পক্ষে কার্যকর হয়নি, তাই আমার 0.02 $ ভাগ করে নিচ্ছেন $

মোকসিটো সংস্করণ: 1.10.19

MyClass.java

private int handleAction(List<String> argList, String action)

Test.java

MyClass spy = PowerMockito.spy(new MyClass());

নিম্নলিখিতগুলি আমার পক্ষে কার্যকর হয়নি (আসল পদ্ধতিটি বলা হচ্ছে):

1।

doReturn(0).when(spy , "handleAction", ListUtils.EMPTY_LIST, new String());

2।

doReturn(0).when(spy , "handleAction", any(), anyString());

3।

doReturn(0).when(spy , "handleAction", null, null);

অনুসরণ করা অনুসরণ করা:

doReturn(0).when(spy , "handleAction", any(List.class), anyString());

0

কোনও ক্লাসের কোনও পদ্ধতি না বলা হয়েছে তা নিশ্চিত করার একটি উপায় হ'ল পদ্ধতিটি ডামি দিয়ে ওভাররাইড করা।

    WebFormCreatorActivity activity = spy(new WebFormCreatorActivity(clientFactory) {//spy(new WebFormCreatorActivity(clientFactory));
            @Override
            public void select(TreeItem i) {
                log.debug("SELECT");
            };
        });

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.