মকিতো স্থানীয়ভাবে চূড়ান্ত শ্রেণির উপহাস করে তবে জেনকিন্সে ব্যর্থ হয়


11

আমি একটি স্ট্যাটিক পদ্ধতির জন্য কিছু ইউনিট পরীক্ষা লিখেছি। স্থির পদ্ধতিতে কেবল একটি যুক্তি লাগে takes যুক্তির ধরণটি একটি চূড়ান্ত শ্রেণি। কোডের ক্ষেত্রে:

public class Utility {

   public static Optional<String> getName(Customer customer) {
       // method's body.
   }
}

public final class Customer {
   // class definition
}

সুতরাং Utilityক্লাসের জন্য আমি একটি পরীক্ষা ক্লাস তৈরি করেছি UtilityTestsযাতে আমি এই পদ্ধতির জন্য পরীক্ষাগুলি লিখেছি getName,। ইউনিট পরীক্ষার কাঠামোটি টেস্টএনজি এবং এটি যে মক্কাগুলি ব্যবহৃত হয় তা হ'ল Mockito। সুতরাং একটি সাধারণ পরীক্ষার নিম্নলিখিত কাঠামো থাকে:

public class UtilityTests {

   @Test
   public void getNameTest() {
     // Arrange
     Customer customerMock = Mockito.mock(Customer.class);
     Mockito.when(...).thenReturn(...);

     // Act
     Optional<String> name = Utility.getName(customerMock);

     // Assert
     Assert.assertTrue(...);
   }
}

সমস্যাটা কি ?

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

org.mockito.exception.base.MockitoEception: ম্যাক / স্পাই ক্লাস com.packagename.Customer মকিতো উপহাস / স্পাই করতে পারেন না কারণ: - চূড়ান্ত শ্রেণি

আমি কি চেষ্টা করেছি?

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

প্রশ্নাবলি

সুতরাং আমার কাছে দুটি প্রশ্ন এখানে রয়েছে:

  1. কিভাবে প্রথম স্থানে এটি সম্ভব? স্থানীয় এবং জেনকিন্স উভয়ই পরীক্ষা ব্যর্থ হওয়া উচিত নয়?
  2. আমি উপরে উল্লিখিত সীমাবদ্ধতার ভিত্তিতে এটি কীভাবে ঠিক করা যায়?

কোনো সাহায্যের জন্য আগাম ধন্যবাদ।


1
আমার অনুমানটিটি enable finalহ'ল কনফিগারেশনটি আপনার ওয়ার্কস্পেসে কাজ করে, তবে যখন চালানো হয় তখন Jenkinsএই ফাইলটি খুঁজে পাওয়া যায় না। Jenkinsফাইলটি কোথায় সন্ধান করছে এবং এটি সেখানে রয়েছে কিনা তা যাচাই করুন।
দ্বিতীয়

এই অন্যান্য থ্রেড কিভাবে, Mockito 2 চূড়ান্ত বর্গ বিদ্রূপকারী সক্ষম করতে সম্পদ ডিরেক্টরি অধীনে একটি mockito কনফিগারেশন ফাইল যোগ করে ব্যাখ্যা করে stackoverflow.com/questions/14292863/...
জোসে Tepedino

3
আপনি যে কোডটির সাথে কথা বলছেন তাতে কি গ্রাহক শ্রেণীর কাছ থেকে একটি ইন্টারফেস বের করা, আইকুস্টোমার বলে, এবং এটি ইউটিলিটি ক্লাসে ব্যবহার করা সম্ভব হবে? তারপর আপনি কংক্রিট চূড়ান্ত ক্লাসের পরিবর্তে যে ইন্টারফেস উপহাস পারে
জোসে Tepedino

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

1
না Customerএটা কোনো যুক্তি থাকে, অথবা এটি শুধু একটি মূক ডেটা ক্লাস হয়? যদি এটি গ্রাহক এবং সেটটার সহ কেবল ক্ষেত্রের একগুচ্ছ হয়, তবে আপনি কেবল এটি ইনস্ট্যানিয়েট করতে পারেন।
উইলিস ব্ল্যাকবার্ন

উত্তর:


2

বিকল্প পদ্ধতি হ'ল 'পদ্ধতিতে শ্রেণি' প্যাটার্ন ব্যবহার করা।

  1. গ্রাহক শ্রেণীর বাইরে থাকা পদ্ধতিগুলি অন্য শ্রেণি / শ্রেণিতে স্থানান্তরিত করুন, গ্রাহকসোমথিং যেমন / গ্রাহকফিনান্স (বা যা কিছু তার দায়বদ্ধ) বলুন।
  2. গ্রাহককে একটি কনস্ট্রাক্টর যুক্ত করুন।
  3. এখন আপনার গ্রাহককে উপহাস করার দরকার নেই, কেবলমাত্র গ্রাহকসমাংস ক্লাস! আপনার যদি কোনও বাহ্যিক নির্ভরতা না থাকে তবে আপনাকে এটি উপহাস করার প্রয়োজন হতে পারে না।

বিষয়টির জন্য এখানে একটি ভাল ব্লগ রয়েছে: https://simpleprogrammer.com/back-to-basics-mock-eliminating-patterns/


1
আপনার উত্তর (+1) জন্য ধন্যবাদ। আমি এটি ঠিক করার একটি উপায় খুঁজে পেয়েছি (দ্বিতীয় প্রশ্নের উত্তর)। তবে কেন ইন্টেলিজজের অভ্যন্তরে পরীক্ষাগুলি ব্যর্থ হয় তা এখনও আমার কাছে পরিষ্কার নয়। তদ্ব্যতীত, আমি এটি আর পুনরুত্পাদন করতে পারি না (ইন্টেলিজজের অভ্যন্তরে ব্যর্থতা), যা সম্পূর্ণ অদ্ভুত।
ক্রিস্টোস

1

কিভাবে প্রথম স্থানে এটি সম্ভব? স্থানীয় এবং জেনকিন্স উভয়ই পরীক্ষা ব্যর্থ হওয়া উচিত নয়?

এটি স্পষ্টতই এক ধরণের vভ-স্পেসিফিক্স। একমাত্র প্রশ্ন - পার্থক্যের কারণটি কীভাবে নির্ধারণ করা যায়।

আমি আপনাকে org.mockito.internal.util.MockUtil#typeMockabilityOfপদ্ধতিটি যাচাই করতে এবং তুলনা করার পরামর্শ দিচ্ছি , mockMakerবাস্তবে কী পরিবেশ এবং কেন উভয় ক্ষেত্রে ব্যবহৃত হয়।

যদি mockMakerএকই হয় - ভারী ভার্সন IDE-Clientবনাম তুলনা করুন Jenkins-Client- পরীক্ষা কার্যকর করার সময় তাদের কোনও পার্থক্য রয়েছে কি?

আমি উপরে উল্লিখিত সীমাবদ্ধতার ভিত্তিতে এটি কীভাবে ঠিক করা যায়?

নিম্নলিখিত কোডটি ওপেনজেডকে 12 এবং মকিতো 2.28.2 অনুমান করে লেখা হয়েছে, তবে আমি বিশ্বাস করি আপনি এটি কোনও ব্যবহৃত ব্যবহৃত সংস্করণে সামঞ্জস্য করতে পারেন।

public class UtilityTest {    
    @Rule
    public InlineMocksRule inlineMocksRule = new InlineMocksRule();

    @Rule
    public MockitoRule mockitoRule = MockitoJUnit.rule();

    @Test
    public void testFinalClass() {
        // Given
        String testName = "Ainz Ooal Gown";
        Client client = Mockito.mock(Client.class);
        Mockito.when(client.getName()).thenReturn(testName);

        // When
        String name = Utility.getName(client).orElseThrow();

        // Then
        assertEquals(testName, name);
    }

    static final class Client {
        final String getName() {
            return "text";
        }
    }

    static final class Utility {
        static Optional<String> getName(Client client) {
            return Optional.ofNullable(client).map(Client::getName);
        }
    }    
}

ইনলাইন উপহাসের জন্য পৃথক নিয়ম সহ:

import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import org.mockito.internal.configuration.plugins.Plugins;
import org.mockito.internal.util.MockUtil;

import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public class InlineMocksRule implements TestRule {
    private static Field MOCK_MAKER_FIELD;

    static {
        try {
            MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(Field.class, MethodHandles.lookup());
            VarHandle modifiers = lookup.findVarHandle(Field.class, "modifiers", int.class);

            MOCK_MAKER_FIELD = MockUtil.class.getDeclaredField("mockMaker");
            MOCK_MAKER_FIELD.setAccessible(true);

            int mods = MOCK_MAKER_FIELD.getModifiers();
            if (Modifier.isFinal(mods)) {
                modifiers.set(MOCK_MAKER_FIELD, mods & ~Modifier.FINAL);
            }
        } catch (IllegalAccessException | NoSuchFieldException ex) {
            throw new RuntimeException(ex);
        }
    }

    @Override
    public Statement apply(Statement base, Description description) {
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                Object oldMaker = MOCK_MAKER_FIELD.get(null);
                MOCK_MAKER_FIELD.set(null, Plugins.getPlugins().getInlineMockMaker());
                try {
                    base.evaluate();
                } finally {
                    MOCK_MAKER_FIELD.set(null, oldMaker);
                }
            }
        };
    }
}

আপনার উত্তর (+1) জন্য ধন্যবাদ। আমি এটি ঠিক করার একটি উপায় খুঁজে পেয়েছি (দ্বিতীয় প্রশ্নের উত্তর)। তবে কেন ইন্টেলিজজের অভ্যন্তরে পরীক্ষাগুলি ব্যর্থ হয় তা এখনও আমার কাছে পরিষ্কার নয়। তদ্ব্যতীত, আমি এটি আর পুনরুত্পাদন করতে পারি না (ইন্টেলিজজের অভ্যন্তরে ব্যর্থতা), যা সম্পূর্ণ অদ্ভুত।
ক্রিস্টোস

1

নিশ্চিত করুন যে আপনি একই যুক্তি দিয়ে পরীক্ষাটি চালাচ্ছেন। আপনার ইন্টেলিজ রান কনফিগারেশনগুলি জেনকিনগুলির সাথে মেলে কিনা তা পরীক্ষা করুন। https://www.jetbrains.com/help/idea/creating-and-editing-run-debug-configurations.html । আপনি জেনকিন্স (টার্মিনাল থেকে) এর মতো একই আর্গুমেন্টের সাহায্যে স্থানীয় মেশিনে পরীক্ষা চালানোর চেষ্টা করতে পারেন, যদি এটি ব্যর্থ হয় তবে সমস্যাটি আর্গুমেন্টে রয়েছে


ফাইলটি org.mockito.plugins.MockMakerজেনকিন্স মেশিনেও রয়েছে। আমি বট মেশিনে একই জেভিএম ব্যবহার করি। আপনি চিহ্নিত তিনটি আমি পরীক্ষা করব। ধন্যবাদ
ক্রিস্টোস

জেনকিন্সে ব্যবহৃত কমান্ডটি ব্যবহার করে কনসোলের মাধ্যমে পরীক্ষা চালানোর চেষ্টা করেছি। তারা একই সঠিক ত্রুটি বার্তা দিয়ে ব্যর্থ। সুতরাং ইন্টেলিজির ভিতরে অদ্ভুত কিছু ঘটে।
ক্রিস্টোস

আপনার রান কনফিগারেশনে .idea / workpace.xML এ একবার দেখুন, এটি <কম্পোনেন্ট> ট্যাগের অভ্যন্তরে। এর পরে আপনি কীভাবে সেই এক্সএমএলটিকে ব্যাশ কমান্ডে রূপান্তর করতে পারেন
লিংক 182

আপনি কি জেনকিনস টার্মিনাল কমান্ড প্রদর্শন করতে পারেন যা পরীক্ষা চালাতে ব্যবহৃত হয়? এছাড়াও আপনি আমাকে বলতে পারেন আপনি কোন প্যাকেজ ম্যানেজার ব্যবহার করেন?
182

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