আমি কীভাবে একটি JUnit পরীক্ষার অপেক্ষা করতে পারি?


95

আমার একটি JUnit পরীক্ষা রয়েছে যা আমি সিঙ্ক্রোনালি সময়ের জন্য অপেক্ষা করতে চাই। আমার JUnit পরীক্ষাটি এর মতো দেখাচ্ছে:

@Test
public void testExipres(){
    SomeCacheObject sco = new SomeCacheObject();
    sco.putWithExipration("foo", 1000);
    // WAIT FOR 2 SECONDS
    assertNull(sco.getIfNotExipred("foo"));
}

আমি চেষ্টা করেছি Thread.currentThread().wait(), তবে এটি একটি অবৈধমনিটর স্টেটএক্সেপশন ছুড়ে ফেলেছে (প্রত্যাশার মতো)।

এটিতে কিছু কৌশল আছে নাকি আমার আলাদা মনিটরের দরকার আছে?

উত্তর:


119

কীভাবে Thread.sleep(2000);? :)


15
আপনি যদি সোনারকুবের মতো কোড বিশ্লেষণ সরঞ্জামগুলি ব্যবহার করেন তবে তারা থ্রেড ব্যবহার করারThread.sleep মতো কিছু বলার বিষয়ে অভিযোগ করবেন s একটি পরীক্ষায় ঘুমান কেবল একটি খারাপ ধারণা। এটি ভঙ্গুর পরীক্ষা তৈরি করে যা পরিবেশের উপর নির্ভর করে ("আমার মেশিনে পাস!") বা লোডের উপর নির্ভর করে অনাকাঙ্ক্ষিতভাবে ব্যর্থ হতে পারে। টাইমিংয়ের উপর নির্ভর করবেন না (মক ব্যবহার করুন) বা অ্যাসিঙ্ক্রোনাস পরীক্ষার জন্য ওয়েবেটিলিটির মতো লাইব্রেরি ব্যবহার করবেন না।
ফিউরিফার্ট

4
এই উত্তরটি সরানো উচিত এবং ক্ষতিকারক হিসাবে বিবেচিত হওয়া উচিত। নিচে একটি অনেক ভালো উত্তর stackoverflow.com/a/35163873/1229735
yiati

73

থ্রেড.স্লিপ () বেশিরভাগ ক্ষেত্রে কাজ করতে পারে তবে সাধারণত আপনি যদি অপেক্ষা করেন, আপনি আসলে কোনও নির্দিষ্ট অবস্থা বা অবস্থা হওয়ার জন্য অপেক্ষা করছেন। থ্রেড.স্লিপ () গ্যারান্টি দেয় না যে আপনি যা যা অপেক্ষা করেছিলেন তা আসলে ঘটেছে।

উদাহরণস্বরূপ আপনি যদি বিশ্রামের অনুরোধের অপেক্ষায় থাকেন তবে এটি সাধারণত 5 সেকেন্ডের মধ্যে ফিরে আসে তবে আপনি যদি 10 মিনিটের মধ্যে আপনার অনুরোধটি ফিরে আসে আপনি 5 সেকেন্ডের জন্য ঘুম স্থির করেন তবে আপনার পরীক্ষাটি ব্যর্থ হতে চলেছে।

এই জয়ওয়াইয়ের প্রতিকারের জন্য আউটিলিটি নামে একটি দুর্দান্ত ইউটিলিটি রয়েছে যা আপনার এগিয়ে যাওয়ার আগে একটি নির্দিষ্ট শর্তটি নিশ্চিত হওয়ার জন্য উপযুক্ত।

এটির পাশাপাশি একটি দুর্দান্ত সাবলীল এপিও রয়েছে

await().until(() -> 
{
    return yourConditionIsMet();
});  

https://github.com/jayway/awaitility


অ্যান্ড্রয়েড স্টুডিওতে সংকলনের জন্য আমি অপেক্ষা করতে পারিনি।
ইগোরগানাপলস্কি

আপনি কি এই লাইনটি গ্রেড ফাইলটিতে সংযুক্ত করেছেন: সংকলন 'org.awaitility: প্রতীক্ষা: 3.0.0'?
সামোহট

না আপনি এটি কোনও পরীক্ষার ক্ষেত্রে যুক্ত করবেন যেখানে আপনি কোনও বিশেষ শর্তের জন্য অপেক্ষা করতে চান
বেন গ্লাসার

16

যদি আপনার স্ট্যাটিক কোড বিশ্লেষক (সোনারকিউবের মতো) অভিযোগ করে তবে আপনি ঘুমের চেয়ে অন্য কোনও উপায় সম্পর্কে ভাবতে পারবেন না, আপনি হ্যাকের মতো চেষ্টা করতে পারেন: Awaitility.await().pollDelay(Durations.ONE_SECOND).until(() -> true); এটি ধারণাগতভাবে ভুল, তবে এটি একই Thread.sleep(1000)

অবশ্যই সবচেয়ে ভাল উপায় হ'ল trueআমার কাছে যা আছে তার পরিবর্তে আপনার উপযুক্ত অবস্থার সাথে একটি কলযোগ্য পাস করা।

https://github.com/awaitility/awaitility


@ জিতেন্দ্র: নোট করুন যে অপেক্ষার Durationক্লাস থাকত , তবে ৪ র্থ সংস্করণ থেকে তারা এর নাম পরিবর্তন করে রেখেছিল Durations
জ্যাকব ভ্যান লিনজেন

একটি সতর্কতা, আপনি যদি জরিপের বিলম্বটি 10 ​​সেকেন্ড বা তার বেশি হতে চান তবে সময়সীমাটি 10 ​​সেকেন্ডেরও বেশি বাড়ানোর বিষয়টি নিশ্চিত করুন যেহেতু এটি ডিফল্ট সময়সীমা এবং প্রতীক্ষার অভিযোগ করবে যে ভোটদানের বিলম্বের চেয়ে সময়সীমা কম less
ফোকাস করুন

15

আপনি java.util.concurrent.TimeUnit লাইব্রেরি ব্যবহার করতে পারেন যা অভ্যন্তরীণভাবে Thread.sંઘ ব্যবহার করে। সিনট্যাক্সটি দেখতে দেখতে এটির মতো হওয়া উচিত:

@Test
public void testExipres(){
    SomeCacheObject sco = new SomeCacheObject();
    sco.putWithExipration("foo", 1000);

    TimeUnit.MINUTES.sleep(2);

    assertNull(sco.getIfNotExipred("foo"));
}

এই গ্রন্থাগারটি সময় ইউনিটের জন্য আরও স্পষ্ট ব্যাখ্যা প্রদান করে। আপনি 'ঘন্টা' / 'মিনিট' / 'সেকেন্ডস' ব্যবহার করতে পারেন।


যদি আমি একটি পরীক্ষার মধ্যে থেকে কোনও শ্রমিকের থ্রেড শুরু করি, sleep()তবে শ্রমিক থ্রেডকে প্রভাবিত করবে ?
অ্যান্টনি কং


0

একটি সাধারণ সমস্যা আছে: সময়কে উপহাস করা শক্ত। এছাড়াও, একটি ইউনিট পরীক্ষায় দীর্ঘ চলমান / অপেক্ষার কোড স্থাপন করা সত্যিই খারাপ অভ্যাস।

সুতরাং, একটি নির্ধারিত এপিআই পরীক্ষারযোগ্য করার জন্য, আমি এই জাতীয় এবং একটি মক বাস্তবায়ন সহ একটি ইন্টারফেস ব্যবহার করেছি:

public interface Clock {

    public long getCurrentMillis();

    public void sleep(long millis) throws InterruptedException;

}

public static class SystemClock implements Clock {

    @Override
    public long getCurrentMillis() {
        return System.currentTimeMillis();
    }

    @Override
    public void sleep(long millis) throws InterruptedException {
        Thread.sleep(millis);
    }

}

public static class MockClock implements Clock {

    private final AtomicLong currentTime = new AtomicLong(0);


    public MockClock() {
        this(System.currentTimeMillis());
    }

    public MockClock(long currentTime) {
        this.currentTime.set(currentTime);
    }


    @Override
    public long getCurrentMillis() {
        return currentTime.addAndGet(5);
    }

    @Override
    public void sleep(long millis) {
        currentTime.addAndGet(millis);
    }

}

এটির সাহায্যে আপনি নিজের পরীক্ষায় সময় নকল করতে পারেন:

@Test
public void testExipres() {
    MockClock clock = new MockClock();
    SomeCacheObject sco = new SomeCacheObject();
    sco.putWithExipration("foo", 1000);
    clock.sleep(2000) // WAIT FOR 2 SECONDS
    assertNull(sco.getIfNotExpired("foo"));
}

এর জন্য একটি উন্নত মাল্টি-থ্রেডিং মক Clockঅবশ্যই আরও জটিল, তবে আপনি এটি ThreadLocalউল্লেখ এবং একটি ভাল সময়ের সিঙ্ক্রোনাইজেশন কৌশল দ্বারা তৈরি করতে পারেন , উদাহরণস্বরূপ।


0

যদি কোনও পরীক্ষায় দেরি করা একেবারে প্রয়োজনীয় হয় তবে এটি CountDownLatchএকটি সহজ সমাধান। আপনার পরীক্ষার শ্রেণিতে ঘোষণা করুন:

private final CountDownLatch waiter = new CountDownLatch(1);

এবং পরীক্ষা যেখানে প্রয়োজন:

waiter.await(1000 * 1000, TimeUnit.NANOSECONDS); // 1ms

বলা অপ্রয়োজনীয় তবে মনে রাখতে হবে যে আপনার অপেক্ষা করার সময়টি ছোট রাখা উচিত এবং খুব বেশি জায়গায় অপেক্ষা করা উচিত নয়।

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