মকিতো ব্যবহার করার সময় বিদ্রূপ ও গুপ্তচরবৃত্তির মধ্যে পার্থক্য কী?


137

মকিতো গুপ্তচর ব্যবহারের জন্য ব্যবহারের ক্ষেত্রে কী হবে?

আমার কাছে মনে হয় প্রতিটি স্পাই ব্যবহারের ক্ষেত্রে কল রিলিমথোড ব্যবহার করে একটি উপহাসের মাধ্যমে পরিচালনা করা যায়।

একটি পার্থক্য যা আমি দেখতে পাচ্ছি তা হল আপনি যদি বেশিরভাগ পদ্ধতির কলগুলি বাস্তব হতে চান তবে এটি একটি মক বনাম একটি গুপ্তচর ব্যবহার করতে কোডের কয়েকটি লাইন সংরক্ষণ করে। এটা নাকি আমি বড় ছবিটি মিস করছি?

উত্তর:


100

উত্তরটি ডকুমেন্টেশনে রয়েছে :

আসল আংশিক উপহাস (1.8.0 সাল থেকে)

অবশেষে, মেলিং তালিকায় অনেক অভ্যন্তরীণ বিতর্ক এবং আলোচনার পরে মকিতোতে আংশিক মক সমর্থন যোগ করা হয়েছিল। পূর্বে আমরা আংশিক মককে কোডের গন্ধ হিসাবে বিবেচনা করি। তবে আমরা আংশিক উপহাসের জন্য বৈধ ব্যবহারের কেসটি পেয়েছি।

রিলিজের আগে 1.8 স্পাই () প্রকৃত আংশিক উপহাস তৈরি করছিল না এবং এটি কিছু ব্যবহারকারীর জন্য বিভ্রান্তিকর ছিল। গুপ্তচরবৃত্তি সম্পর্কে আরও পড়ুন: এখানে বা গুপ্তচর (অবজেক্ট) পদ্ধতির জন্য জাভাদোক।

callRealMethod()এর পরে পরিচয় করা হয়েছিল spy(), তবে পিছনে সামঞ্জস্যতা নিশ্চিত করতে গুপ্তচর () অবশ্যই সেখানে রেখে দেওয়া হয়েছিল।

অন্যথায়, আপনি ঠিক বলেছেন: কোনও স্পাইয়ের সমস্ত পদ্ধতি সত্যিকারের স্ট্যাড না দেওয়া পর্যন্ত। মোক না callRealMethod()বলা ব্যতীত মোকের সমস্ত পদ্ধতি স্ট্যাবড হয়। সাধারণভাবে, আমি ব্যবহার পছন্দ করি callRealMethod(), কারণ এটি আমাকে doXxx().when()প্রথাগতের পরিবর্তে আইডিয়ামটি ব্যবহার করতে বাধ্য করে নাwhen().thenXxx()


এই ক্ষেত্রে গুপ্তচরবৃত্তির তুলনায় মোককে অগ্রাধিকার দেওয়ার সমস্যাটি যখন শ্রেণিটি এমন কোনও সদস্যকে ব্যবহার করে যা এতে ectedুকিয়ে দেওয়া হয় না (তবে স্থানীয়ভাবে শুরু করা হয়), এবং পরে "আসল" পদ্ধতি দ্বারা ব্যবহৃত হয়; উপহাসে, সদস্যটিকে তার ডিফল্ট জাভা মান থেকে আরম্ভ করা হবে, যা ভুল আচরণ বা এমনকি একটি নলপয়েন্টার এক্সসেপশন হতে পারে। এটি পাস করার উপায়টি হল একটি "আরআইআই" পদ্ধতি যুক্ত করা এবং তারপরে এটি "কল্পনা" করা, তবে এটি আমার কাছে কিছুটা বাড়তি মনে হয়।
আইয়াল রথ

দস্তাবেজ থেকে: "গুপ্তচরদের যত্ন সহকারে এবং মাঝে মধ্যে ব্যবহার করা উচিত, উদাহরণস্বরূপ যখন উত্তরাধিকারের কোডটি নিয়ে কাজ করা হয়।" ইউনিট পরীক্ষার স্থান একই জিনিসটি করার অনেকগুলি উপায়ে ভুগছে।
gdbj

89

একটি স্পাই এবং একটি মক মধ্যে পার্থক্য

যখন মকিতো একটি উপহাস তৈরি করে - এটি কোনও ধরণের শ্রেণি থেকে এমনটি করে, প্রকৃত উদাহরণ থেকে নয়। মোক এটি ক্লাসের একটি খালি-হাড়ের শেল উদাহরণ তৈরি করে, এটির সাথে ইন্টারঅ্যাকশনগুলি ট্র্যাক করার জন্য পুরোপুরি জিভ হয়। অন্যদিকে, গুপ্তচর একটি বিদ্যমান উদাহরণ মোড়ানো করবে। এটি এখনও সাধারণ উদাহরণের মতো একইভাবে আচরণ করবে - পার্থক্যটি হ'ল এটির সাথে সমস্ত মিথস্ক্রিয়াও ট্র্যাক করার জন্য এটি চালিত হবে।

নিম্নলিখিত উদাহরণে - আমরা অ্যারেলিস্ট শ্রেণীর একটি উপহাস তৈরি করি:

@Test
public void whenCreateMock_thenCreated() {
    List mockedList = Mockito.mock(ArrayList.class);

    mockedList.add("one");
    Mockito.verify(mockedList).add("one");

    assertEquals(0, mockedList.size());
}

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

@Test
public void whenCreateSpy_thenCreate() {
    List spyList = Mockito.spy(new ArrayList());
    spyList.add("one");
    Mockito.verify(spyList).add("one");

    assertEquals(1, spyList.size());
}

এখানে আমরা অবশ্যই বলতে পারি যে বস্তুর আসল অভ্যন্তরীণ পদ্ধতিটি বলা হয়েছিল কারণ আপনি যখন আকার () পদ্ধতিটি কল করেন তখন আপনি আকারটি 1 হিসাবে পান তবে এই আকার () পদ্ধতিটি উপহাস করা হয়নি! তাহলে 1 কোথা থেকে আসে? অভ্যন্তরীণ আসল আকার () পদ্ধতিটিকে আকার হিসাবে বলা হয় () উপহাস করা হয় না (বা স্ট্যাবড হয়) এবং তাই আমরা বলতে পারি যে আসল বস্তুতে এন্ট্রি যুক্ত হয়েছিল।

সূত্র: http://www.baeldung.com/mockito-spy + স্ব নোট।


1
আপনি কি আকার বলতে চান না () 1 প্রদান?
কালো

প্রথম উদাহরণে, কেন যদি সেই পদ্ধতিটি ছড়িয়ে দেওয়া না হয় তবে কেন mockedList.size()ফিরে আসছেন 0? পদ্ধতির রিটার্ন ধরণের দেওয়া কি এটি একটি ডিফল্ট মান?
মাইক

@ মাইক: জাভাতে 0 এবং এর mockedList.size()একটি intডিফল্ট মান প্রদান করে int। আপনি যদি assertEquals(0, mockedList.size());পরে মৃত্যুদন্ড কার্যকর করার চেষ্টা করেন mockedList.clear();, ফলাফল একই থাকে।
রিয়েলপিকে

2
এই উত্তরটি ভাল এবং সহজভাবে লিখিত এবং অবশেষে উপহাস এবং গুপ্তচরর মধ্যে পার্থক্য বুঝতে আমাকে সহায়তা করেছে। সুন্দর.
PesaThe

38

যদি 8 টি পদ্ধতি সহ কোনও অবজেক্ট থাকে এবং আপনার কাছে এমন একটি পরীক্ষা রয়েছে যেখানে আপনি 7 টি বাস্তব পদ্ধতি কল করতে চান এবং একটি পদ্ধতিতে স্ট্যাব করতে পারেন আপনার দুটি বিকল্প রয়েছে:

  1. একটি উপহাস ব্যবহার করে আপনাকে এটি 7 কল কল রিলেমথোড এবং একটি পদ্ধতি স্টাব করে সেট আপ করতে হবে
  2. একটি ব্যবহার করে spyআপনাকে একটি পদ্ধতি স্টাব করে সেট আপ করতে হবে

সরকারী ডকুমেন্টেশন উপর doCallRealMethodআংশিক ঠাট্টা জন্য একটি গুপ্তচর ব্যবহার পরামর্শ দেওয়া হচ্ছে।

আংশিক উপহাস সম্পর্কে আরও জানতে জাভাদোক স্পাই (অবজেক্ট) দেখুন। মকিতো.স্পাই () হ'ল আংশিক মক তৈরির প্রস্তাবিত উপায়। কারণটি হ'ল গ্যারান্টি দেয় যে প্রকৃত পদ্ধতিগুলি সঠিকভাবে নির্মিত বস্তুর বিরুদ্ধে বলা হয়েছিল কারণ আপনি গুপ্তচর () পদ্ধতিতে পাস করা অবজেক্টটি তৈরির জন্য দায়বদ্ধ।


5

লিগ্যাসি কোডের জন্য ইউনিট পরীক্ষা তৈরি করতে চাইলে স্পাই দরকারী হতে পারে ।

আমি এখানে একটি চলমান উদাহরণ তৈরি করেছি https://www.surasint.com/mockito-with-spy/ , আমি এর কয়েকটি এখানে অনুলিপি করছি।

আপনার কাছে এই কোডের মতো কিছু থাকলে:

public void transfer(  DepositMoneyService depositMoneyService, WithdrawMoneyService withdrawMoneyService, 
             double amount, String fromAccount, String toAccount){
    withdrawMoneyService.withdraw(fromAccount,amount);
    depositMoneyService.deposit(toAccount,amount);
}

আপনার গোয়েন্দাগুলির প্রয়োজন নেই কারণ আপনি কেবল ডিপোজিটমনি সার্ভিস এবং উইথড্রোমনি সার্ভিসেসকে উপহাস করতে পারেন।

তবে কিছু সহ, লিগ্যাসি কোড, নির্ভরতা এই কোডগুলিতে থাকে:

    public void transfer(String fromAccount, String toAccount, double amount){

        this.depositeMoneyService = new DepositMoneyService();
        this.withdrawMoneyService = new WithdrawMoneyService();

        withdrawMoneyService.withdraw(fromAccount,amount);
        depositeMoneyService.deposit(toAccount,amount);
    }

হ্যাঁ, আপনি প্রথম কোডে পরিবর্তন করতে পারেন তবে তারপরে এপিআই পরিবর্তন করা হয়। যদি এই পদ্ধতিটি অনেক জায়গায় ব্যবহার করা হয় তবে আপনাকে সেগুলি সব পরিবর্তন করতে হবে।

বিকল্পটি হ'ল আপনি নির্ভরতাটি এর বাইরে বের করতে পারেন:

    public void transfer(String fromAccount, String toAccount, double amount){
        this.depositeMoneyService = proxyDepositMoneyServiceCreator();
        this.withdrawMoneyService = proxyWithdrawMoneyServiceCreator();

        withdrawMoneyService.withdraw(fromAccount,amount);
        depositeMoneyService.deposit(toAccount,amount);
    }
    DepositMoneyService proxyDepositMoneyServiceCreator() {
        return new DepositMoneyService();
    }

    WithdrawMoneyService proxyWithdrawMoneyServiceCreator() {
        return new WithdrawMoneyService();
    }

তারপরে আপনি গুপ্তচরকে ইনজেকশনটি এভাবে নির্ভরতা ব্যবহার করতে পারেন:

DepositMoneyService mockDepositMoneyService = mock(DepositMoneyService.class);
        WithdrawMoneyService mockWithdrawMoneyService = mock(WithdrawMoneyService.class);

    TransferMoneyService target = spy(new TransferMoneyService());

    doReturn(mockDepositMoneyService)
            .when(target).proxyDepositMoneyServiceCreator();

    doReturn(mockWithdrawMoneyService)
            .when(target).proxyWithdrawMoneyServiceCreator();

উপরের লিঙ্কে আরও বিশদ।


0

Mockখালি ডাবল অবজেক্ট। এই অবজেক্টে একই পদ্ধতিতে স্বাক্ষর রয়েছে তবে উপলব্ধিটি খালি এবং ডিফল্ট মান - 0 এবং নাল ফেরান

Spyএকটি ক্লোনড ডাবল অবজেক্ট। নতুন অবজেক্টটি রিয়েল অবজেক্টের উপর ভিত্তি করে ক্লোন করা হয়েছে তবে আপনার এটি উপহাস করার সম্ভাবনা রয়েছে

class A {

    String foo1() {
        foo2();
        return "RealString_1";
    }

    String foo2() {
        return "RealString_2";
    }

    void foo3() {
        foo4();
    }

    void foo4() {

    }
}
@Test
public void testMockA() {

    //given
    A mockA = Mockito.mock(A.class);
    Mockito.when(mockA.foo1()).thenReturn("MockedString");

    //when
    String result1 = mockA.foo1();
    String result2 = mockA.foo2();

    //then
    assertEquals("MockedString", result1);
    assertEquals(null, result2);

    //Case 2
    //when
    mockA.foo3();

    //then
    verify(mockA).foo3();
    verify(mockA, never()).foo4();
}

@Test
public void testSpyA() {
    //given
    A spyA = Mockito.spy(new A());

    Mockito.when(spyA.foo1()).thenReturn("MockedString");

    //when
    String result1 = spyA.foo1();
    String result2 = spyA.foo2();

    //then
    assertEquals("MockedString", result1);
    assertEquals("RealString_2", result2);

    //Case 2
    //when
    spyA.foo3();

    //then
    verify(spyA).foo3();
    verify(spyA).foo4();
}

[পরীক্ষার দ্বিগুণ]

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