মকিতো: বাউন্ডেড ওয়াইল্ড-কার্ডের সাথে টাইপ করে এমন স্টাবিং পদ্ধতি


135

এই কোডটি বিবেচনা করুন:

public class DummyClass {
    public List<? extends Number> dummyMethod() {
        return new ArrayList<Integer>();
    }
}
public class DummyClassTest {
    public void testMockitoWithGenerics() {
        DummyClass dummyClass = Mockito.mock(DummyClass.class);
        List<? extends Number> someList = new ArrayList<Integer>();
        Mockito.when(dummyClass.dummyMethod()).thenReturn(someList); //Compiler complains about this
    }
}

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


জেনেরিক প্রকারগুলি প্রদর্শন করতে আপনি কি আপনার কোড স্নিপেট আপডেট করতে পারবেন?
মিলহাউস

1
সম্পন্ন. আমাকে প্রি এবং কোড ট্যাগগুলি সরিয়ে ফেলতে হয়েছিল, সেগুলি <স্ট্রিপিং-অফ ছিল? প্রকারের ঘোষণা থেকে সংখ্যা> প্রসারিত করে।
শিখর মিশ্র

উত্তর:


190

আপনি এই উদ্দেশ্যে অ-টাইপ নিরাপদ পদ্ধতি doReturn ও ব্যবহার করতে পারেন ,

@Test
public void testMockitoWithGenerics()
{
    DummyClass dummyClass = Mockito.mock(DummyClass.class);
    List<? extends Number> someList = new ArrayList<Integer>();

    Mockito.doReturn(someList).when(dummyClass).dummyMethod();

    Assert.assertEquals(someList, dummyClass.dummyMethod());
}

যেমনটি মকিতোর গুগল গ্রুপে আলোচনা করা হয়েছে

যদিও এটি এর চেয়ে সহজ thenAnswer, আবার মনে রাখবেন এটি নিরাপদ নয় safe আপনি যদি ধরণের সুরক্ষার বিষয়ে উদ্বিগ্ন হন তবে মিলহাউসের উত্তরটি সঠিক।

অতিরিক্ত তথ্য

স্পষ্টত, এখানে পর্যবেক্ষণ করা সংকলক ত্রুটি,

The method thenReturn(List<capture#1-of ? extends Number>) in the type OngoingStubbing<List<capture#1-of ? extends Number>> is not applicable for the arguments (List<capture#2-of ? extends Number>)

আমি বিশ্বাস করি যে সংকলকটি whenকল চলাকালীন প্রথম ওয়াইল্ডকার্ড টাইপ বরাদ্দ করেছে এবং তারপরে কলটিতে দ্বিতীয় ওয়াইল্ডকার্ড টাইপ thenReturnএকইরকম তা নিশ্চিত করতে পারি না ।

দেখে মনে হচ্ছে এটি thenAnswerএই সমস্যার মধ্যে পড়ে না কারণ এটি একটি ওয়াইল্ডকার্ড টাইপ গ্রহণ করার thenReturnসময় একটি নন-ওয়াইল্ডকার্ড প্রকার গ্রহণ করে, যা অবশ্যই ধরা পড়বে। মকিতোর চলমান স্টাবিং থেকে ,

OngoingStubbing<T> thenAnswer(Answer<?> answer);
OngoingStubbing<T> thenReturn(T value);

এটি আংশিকভাবে আমাকেও সহায়তা করে ... তবে আপনি যে তালিকাটি ফিরে প্রত্যাশা করছেন তা খালি না হলে কী হবে?
ttati

খালি তালিকা থাকার পরিবর্তে আপনিও এটি করতে পারেন: <নাম্বার> কিছুসংখ্যক তালিকা = নতুন অ্যারেলিস্ট <Integer> (); someList.add (aNumber);
ttati

32

আমি ধরে নিচ্ছি আপনি someListকিছু জ্ঞাত মান সহ লোড করতে সক্ষম হতে চান ; এখানে এমন একটি দৃষ্টিভঙ্গি যা Answer<T>সমস্ত কিছু টাইপ-সুরক্ষিত রাখতে একটি পরীক্ষিত সহায়তা পদ্ধতির সাথে একত্রে ব্যবহার করে:

@Test
public void testMockitoWithGenericsUsingAnswer()
{
    DummyClass dummyClass =  Mockito.mock(DummyClass.class);

    Answer<List<Integer>> answer = setupDummyListAnswer(77, 88, 99);
    Mockito.when(dummyClass.dummyMethod()).thenAnswer(answer);

    ...
}

private <N extends Number> Answer<List<N>> setupDummyListAnswer(N... values) {
    final List<N> someList = new ArrayList<N>();

    someList.addAll(Arrays.asList(values));

    Answer<List<N>> answer = new Answer<List<N>>() {
        public List<N> answer(InvocationOnMock invocation) throws Throwable {
            return someList;
        }   
    };
    return answer;
}

17

আমি গতকাল একই জিনিস আঘাত। @ ননডেস্ক্রিপ্ট 1 এবং @ মিলহাউস থেকে প্রাপ্ত উভয় উত্তরই আমাকে একটি কার্যকারিতা নির্ধারণ করতে সহায়তা করেছে। আমি @ মিলহাউস হিসাবে একই কোডটি বেশ ব্যবহার করেছি, আমি এটিকে কিছুটা জেনেরিক তৈরি করা বাদ দিয়েছি কারণ আমার ত্রুটিটি একটি কারণে নয় java.util.List, তবে com.google.common.base.Optional। আমার সামান্য সহায়ক পদ্ধতি অতএব যে কোনও ধরণের জন্য Tএবং কেবল নয় List<T>:

public static <T> Answer<T> createAnswer(final T value) {
    Answer<T> dummy = new Answer<T>() {
        @Override
        public T answer(InvocationOnMock invocation) throws Throwable {
            return value;
        }
    };
    return dummy;
}

এই সহায়ক পদ্ধতিতে আপনি লিখতে পারেন:

Mockito.when(dummyClass.dummyMethod()).thenAnswer(createAnswer(someList));

এটি ঠিক জরিমানা সংকলন করে এবং thenReturn(...)পদ্ধতির মতো একই কাজ করে ।

জাভা সংকলকটি যে ত্রুটিটি বের করে তা একটি সংকলক বাগ বা কোডটি সত্যই যদি ভুল হয় তবে কেউ কি জানেন?


এটিকে সোজা, সহজ এবং আমি যতটা কাছে বলতে পারি, সঠিক বলে মনে হচ্ছে। আমি নিশ্চিত না যে মকিতো কেন এর মতো কিছু সরবরাহ করে না ....... যদি না তা করে?
ভ্যাকো

14
জাভা 8 এ এটি সংক্ষিপ্ত করা যেতে পারে: Mockito.when(dummyClass.dummyMethod()).thenAnswer(x -> someList)সুতরাং ইউটিলিটি পদ্ধতির কোনও প্রয়োজন নেই
ফিকোভনিক ২ik

1
@ ফিকোভনিক কী দুর্দান্ত আবিষ্কার "তারপরে উত্তর"!
বোরজব

5

আমি এখানে জাভা 8+ ব্যবহার করে সর্বাধিক মার্জিত সমাধান বলে মনে করি কারণ এটি আরও দৃশ্যমানতা দেওয়ার জন্য আমি ফিকভনিকের মন্তব্যটিকে একটি উত্তরে রূপান্তরিত করছি ।

Mockito ডকুমেন্টেশন ব্যবহার বিশেষ পরামর্শ দেওয়া হচ্ছে doReturn()শুধুমাত্র শেষ উপায় হিসাবে (যেমন গৃহীত উত্তরে প্রস্তাব)।

পরিবর্তে, প্রশ্নের বর্ণিত সংকলক ত্রুটিটি ঘটাতে, প্রস্তাবিত মকিতো when()পদ্ধতির সাথে thenAnswer()এবং একটি ল্যাম্বডা (কোনও সহায়ক পদ্ধতির পরিবর্তে) ব্যবহার করা যেতে পারে :

Mockito.when(mockedClass.mockedMethod()).thenAnswer(x -> resultList)

যদিও এটি কোনও সংকলনের সময় ত্রুটি দেয় না, প্রত্যাশিত তালিকাটি খালি থাকে এমনকি যখন আমরা এন্ট্রি সহ একটি তালিকা পাস করি।
ভেঙ্কটেশ কোল্লা - user2742897

0

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

যেহেতু এই উত্তরটি একটি অনুরূপ প্রশ্ন শো, এছাড়াও আপনি নিম্নলিখিত ব্যবহার করতে পারেন:

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