মকিতো সুপারক্লাসের কোনও পদ্ধতির কলকে কীভাবে উপহাস করবে


95

আমি কিছু পরীক্ষায় মকিতো ব্যবহার করছি।

আমার নিচের ক্লাসগুলি রয়েছে:

class BaseService {  
    public void save() {...}  
}

public Childservice extends BaseService {  
    public void save(){  
        //some code  
        super.save();
    }  
}   

আমি কেবল দ্বিতীয় কল ( super.save) এর উপহাস করতে চাই ChildService। প্রথম কলটিতে আসল পদ্ধতিটি কল করতে হবে। এটা করার কোন উপায় আছে?


এটি কি পাওয়ারমকিতো দিয়ে সমাধান করা যায়?
javaPLAY42

@ জাভাপ্লিজ 42: হ্যাঁ আপনি করতে পারেন: stackoverflow.com/a/23884011/2049986
জ্যাকব ভ্যান লিনজেন

উত্তর:


57

না, মকিতো এটি সমর্থন করে না।

আপনি যে উত্তরটি সন্ধান করছেন এটি এটি নাও হতে পারে তবে আপনি যা দেখছেন তা ডিজাইনের নীতিটি প্রয়োগ না করার লক্ষণ:

উত্তরাধিকারের উপরে পছন্দসই রচনা

আপনি যদি একটি সুপার ক্লাস বাড়ানোর পরিবর্তে কৌশল বের করেন তবে সমস্যাটি চলে গেছে।

তবে আপনাকে যদি কোডটি পরিবর্তন করার অনুমতি না দেওয়া হয় তবে আপনাকে অবশ্যই এটি পরীক্ষা করতে হবে, এবং এই বিশ্রী পথে এখনও আশা আছে। কিছু এওপি সরঞ্জাম (উদাহরণস্বরূপ AspectJ) দিয়ে আপনি সুপার ক্লাস পদ্ধতিতে কোডটি বুনতে পারেন এবং এর সম্পাদন পুরোপুরি (ইয়াক) এড়াতে পারেন। আপনি প্রক্সি ব্যবহার করছেন এটি কাজ করে না, আপনাকে বাইকোড পরিবর্তন করতে হবে (হয় সময় বোনা লোড করুন বা সময় বুনন সংকলন করুন)। এখানে মশকরা ফ্রেমওয়ার্ক রয়েছে যা পাওয়ারমক এবং পাওয়ারমকিতোর মতো এই ধরণের কৌশলটিকে সমর্থন করে।

আমি আপনাকে রিফ্যাক্টরিংয়ের জন্য যেতে পরামর্শ দিই, তবে যদি এটি কোনও বিকল্প না হয় তবে আপনি কিছু মারাত্মক হ্যাকিংয়ের জন্য রয়েছেন।


4
আমি এলএসপির লঙ্ঘন দেখছি না। আমার প্রায় ওপির মতোই সেটআপ রয়েছে: ফাইন্ডএল () পদ্ধতিযুক্ত একটি বেস ডিএও ক্লাস এবং একটি সাবক্লাস ডিএও যা সুপার.ফাইন্ডএল () কে কল করে এবং তার পরে ফলাফলটি বাছাই করে বেস পদ্ধতিটি ওভাররাইড করে। সাবক্লাস সুপারক্লাসটি গ্রহণ করে সমস্ত প্রসঙ্গেই পরিবর্তনযোগ্য। আমি কি তোমার অর্থ ভুল বুঝছি?

4
আমি এলএসপি মন্তব্যটি সরিয়ে ফেলব (এটি উত্তরের সাথে কোনও মূল্য যুক্ত করে না)।
iwein

হ্যাঁ উত্তরাধিকার সফল হয় এবং আমি যে বোকা ফ্রেমওয়ার্কের সাথে আটকে থাকি তা উত্তরাধিকারের সাথে একমাত্র বিকল্প হিসাবে ডিজাইন করা হয়।
শ্রীধর সারনোবাত

ধরে নিই যে আপনি সুপারক্লাসটি নতুন করে ডিজাইন করতে পারবেন না, আপনি //some codesকোডটি এমন কোনও পদ্ধতিতে এক্সট্রাক্ট করতে পারেন যা আলাদাভাবে পরীক্ষা করা যেতে পারে।
ফসমাল

4
ঠিক আছে বুঝেছি. আমি যখন এটি খুঁজছিলাম তখন আমি যা সমাধান করার চেষ্টা করছিলাম তার চেয়ে ভিন্ন সমস্যা, তবে কমপক্ষে সেই ভুল বোঝাবুঝি আমার নিজের সমস্যাটিকে বেস ক্লাসের মক কল করার জন্য সমাধান করেছে (যা আমি সত্যিই ওভাররাইড করি না)।
গিলিয়াম পেরেট

89

যদি আপনার কাছে রিফ্যাক্টরিংয়ের পক্ষে সত্যিই পছন্দ না থাকে তবে আপনি সুপার মেথড কলের সমস্ত বিষয়কে মক / স্টাব করতে পারেন

    class BaseService {

        public void validate(){
            fail(" I must not be called");
        }

        public void save(){
            //Save method of super will still be called.
            validate();
        }
    }

    class ChildService extends BaseService{

        public void load(){}

        public void save(){
            super.save();
            load();
        }
    }

    @Test
    public void testSave() {
        ChildService classToTest = Mockito.spy(new ChildService());

        // Prevent/stub logic in super.save()
        Mockito.doNothing().when((BaseService)classToTest).validate();

        // When
        classToTest.save();

        // Then
        verify(classToTest).load();
    }

4
এই কোড আসলে super.save () আবাহন অধিকার বাধা নেই, তাই আপনি যদি super.save () মধ্যে অনেক কাজ আপনি ঐ সব কল প্রতিরোধ করতে চাই ...
iwein

চমত্কার সমাধানটি যখন আমার সন্তানের ব্যবহারের জন্য একটি সুপারক্লাস পদ্ধতি থেকে একটি উপহাসকৃত মানটি ফিরিয়ে দিতে চাই তখন আমার জন্য বিস্ময়কর কাজ করে, চমত্কার ধন্যবাদ।
গার্নার্ড

14
বৈধতা লুকানো না থাকলে বা সংরক্ষণ পদ্ধতি অন্য কোনও পদ্ধতিতে কল করার পরিবর্তে সরাসরি কাজ না করে এটি দুর্দান্ত কাজ করে। মকিতো তা করে না: মকিতো.ডো কিছুই না ()। যখন ((বেসসেসওয়ার) স্পাই)। সেভ (); এটি সংরক্ষণ কিন্তু উপর childService সংরক্ষণ :( বেস সেবা করবে না 'doNothing
ত্বীবী

আমি এটি আমার কাজ করতে পারি না - এটি সন্তানের পদ্ধতিটিও আটকায়। BaseServiceঅ্যাবস্ট্রাক্ট, যদিও এটি প্রাসঙ্গিক হবে তা আমি দেখতে পাই না।
শ্রীধর সারনোবাত

4
@ শ্রীধর-সারনোবাত হ্যাঁ আমিও একই জিনিসটি দেখছি :( যে কেউ কীভাবে কেবল এটির জন্য লড়াই করতে পারে তা কী জানেন super.validate()?
স্ট্যানটঙ্ক

5

চাইল্ড সার্ভিস.সেভ () পদ্ধতি থেকে বিভিন্ন পদ্ধতিতে কোডটি রিফ্যাকচারিংয়ের বিষয়টি বিবেচনা করুন এবং চাইল্ড সার্ভিস.সেসেভ () পরীক্ষা করার পরিবর্তে নতুন পদ্ধতিটি পরীক্ষা করুন, আপনি সুপার পদ্ধতিতে অপ্রয়োজনীয় কল এড়াতে পারবেন।

উদাহরণ:

class BaseService {  
    public void save() {...}  
}

public Childservice extends BaseService {  
    public void save(){  
        newMethod();    
        super.save();
    }
    public void newMethod(){
       //some codes
    }
} 

1

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


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

1

এমনকি যদি আমি আইভেন প্রতিক্রিয়ার সাথে পুরোপুরি একমত হই (তবে

উত্তরাধিকার উপর রচনা পছন্দ

), আমি স্বীকার করি যে কিছু সময় উত্তরাধিকার ঠিক স্বাভাবিক বলে মনে হয় এবং আমি কেবল ইউনিট পরীক্ষার জন্যই এটি ভেঙে বা রিফেক্টর অনুভব করি না।

সুতরাং, আমার পরামর্শ:

/**
 * BaseService is now an asbtract class encapsulating 
 * some common logic callable by child implementations
 */
abstract class BaseService {  
    protected void commonSave() {
        // Put your common work here
    }

    abstract void save();
}

public ChildService extends BaseService {  
    public void save() {
        // Put your child specific work here
        // ...

        this.commonSave();
    }  
}

এবং তারপরে ইউনিট পরীক্ষায়:

    ChildService childSrv = Mockito.mock(ChildService.class, Mockito.CALLS_REAL_METHODS);

    Mockito.doAnswer(new Answer<Void>() {
        @Override
        public Boolean answer(InvocationOnMock invocation)
                throws Throwable {
            // Put your mocked behavior of BaseService.commonSave() here
            return null;
        }
    }).when(childSrv).commonSave();

    childSrv.save();

    Mockito.verify(childSrv, Mockito.times(1)).commonSave();

    // Put any other assertions to check child specific work is done

0

কারণটি হল আপনার বেস শ্রেণিটি পাবলিক-এড নয়, তবে দৃশ্যমানতার কারণে মকিতো এটিকে বাধা দিতে পারবেন না, যদি আপনি বেস শ্রেণিটিকে জনসাধারণ হিসাবে পরিবর্তন করেন, বা @ ওভাররাইড উপ-শ্রেণিতে (সর্বজনীন), তবে মকিতো এটিকে সঠিকভাবে উপহাস করতে পারে।

public class BaseService{
  public boolean foo(){
    return true;
  }
}

public ChildService extends BaseService{
}

@Test
@Mock ChildService childService;
public void testSave() {
  Mockito.when(childService.foo()).thenReturn(false);

  // When
  assertFalse(childService.foo());
}

8
এই পয়েন্ট হয় না। চাইল্ড সার্ভিসেস foo () ওভাররাইড করা উচিত এবং সমস্যাটি কীভাবে বেসডেসওয়ার্স.ফু () না করে চাইল্ড সার্ভিস.ফু () উপহাস করবেন
অ্যাড্রিয়ান কোস্টার

0

উত্তরাধিকার বিবেচনা করা হলে সবচেয়ে সহজ বিকল্পটি হ'ল সুপারকে কল করার জন্য একটি নতুন পদ্ধতি (প্যাকেজ প্রাইভেট ??) তৈরি করা, আসল দৃষ্টান্তটি গুপ্তচর এবং তারপরে আপনি যেভাবে উপহাস করতে চেয়েছিলেন সেভাবে সুপারফিনডাল () পদ্ধতিটিকে উপহাস করে তোলেন Maybe পিতা বা মাতা ক্লাস এক। এটি কভারেজ এবং দৃশ্যমানতার দিক থেকে নিখুঁত সমাধান নয় তবে এটি কাজ করা উচিত এবং এটি প্রয়োগ করা সহজ।

 public Childservice extends BaseService {
    public void save(){
        //some code
        superSave();
    }

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