Làm cách nào để tôi có thể đợi Kiểm tra JUnit?


93

Tôi có một bài kiểm tra JUnit mà tôi muốn phải đợi một khoảng thời gian, đồng bộ. Kiểm tra JUnit của tôi trông như thế này:

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

Tôi đã thử Thread.currentThread (). Wait (), nhưng nó ném IllegalMonitorStateException (Như mong đợi). Có một số thủ thuật với nó, hoặc tôi cần một màn hình khác?

Câu trả lời:


117

Làm thế nào về Thread.sleep(2000);? :)


14
Nếu bạn đang sử dụng các công cụ phân tích mã như sonarqube, họ sẽ phàn nàn về việc Thread.sleepnói điều gì đó như Sử dụng Thread.sleep trong thử nghiệm nói chung là một ý tưởng tồi. Nó tạo ra các bài kiểm tra giòn có thể thất bại không thể đoán trước tùy thuộc vào môi trường ("Đạt trên máy của tôi!") Hoặc tải. Không dựa vào thời gian (sử dụng mocks) hoặc sử dụng các thư viện như Awaitility để kiểm tra không đồng bộ.
FuryFart

3
Câu trả lời này nên bị loại bỏ và bị coi là có hại. Câu trả lời tốt hơn nhiều bên dưới là stackoverflow.com/a/35163873/1229735
yiati

71

Thread.sleep () có thể hoạt động trong hầu hết các trường hợp, nhưng thông thường nếu bạn đang đợi, bạn thực sự đang đợi một điều kiện hoặc trạng thái cụ thể xảy ra. Thread.sleep () không đảm bảo rằng bất cứ điều gì bạn đang chờ đợi đã thực sự xảy ra.

Ví dụ, nếu bạn đang chờ một yêu cầu nghỉ ngơi, có thể nó thường quay lại sau 5 giây, nhưng nếu bạn đặt chế độ ngủ trong 5 giây vào ngày yêu cầu của bạn quay lại sau 10 giây thì bài kiểm tra của bạn sẽ không thành công.

Để khắc phục điều này JayWay có một tiện ích tuyệt vời được gọi là Awability , tiện ích hoàn hảo để đảm bảo rằng một điều kiện cụ thể xảy ra trước khi bạn tiếp tục.

Nó cũng có một api thông thạo tuyệt vời

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

https://github.com/jayway/awaitility


Tôi không thể chờ đợi để biên dịch trong Android Studio.
IgorGanapolsky

Bạn đã thêm dòng này vào tệp gradle: biên dịch 'org.awaitility: awaitility: 3.0.0'?
Samoht

Không. bạn sẽ thêm điều này trong một trường hợp thử nghiệm, nơi bạn muốn chờ đợi cho một điều kiện đặc biệt
Bến Glasser

15

Trong trường hợp trình phân tích mã tĩnh của bạn (như SonarQube) phàn nàn, nhưng bạn không thể nghĩ ra cách khác, thay vì ngủ, bạn có thể thử với một hack như: Awaitility.await().pollDelay(Durations.ONE_SECOND).until(() -> true); Nó không chính xác về mặt khái niệm, nhưng nó giống như Thread.sleep(1000).

Tất nhiên, cách tốt nhất là vượt qua Callable, với điều kiện thích hợp của bạn, thay vì điều kiện truemà tôi có.

https://github.com/awaitility/awaitility


@Jitendra: Lưu ý rằng Awaitility từng có Durationlớp này, nhưng kể từ phiên bản 4, họ đã đổi tên nó thành Durations.
Jacob van Lingen

Một lưu ý, nếu bạn muốn độ trễ cuộc thăm dò từ 10 giây trở lên, hãy đảm bảo tăng thời gian chờ lên hơn 10 giây vì đó là thời gian chờ mặc định và sự chờ đợi sẽ phàn nàn rằng thời gian chờ ít hơn độ trễ cuộc thăm dò.
tiêu điểm

12

Bạn có thể sử dụng thư viện java.util.concurrent.TimeUnit sử dụng nội bộ Thread.sleep. Cú pháp sẽ giống như sau:

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

    TimeUnit.MINUTES.sleep(2);

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

Thư viện này cung cấp cách giải thích rõ ràng hơn cho đơn vị thời gian. Bạn có thể sử dụng 'HOURS' / 'MINUTES' / 'SECONDS'.


Nếu tôi bắt đầu một luồng công nhân từ trong một bài kiểm tra, thì liệu có sleep()ảnh hưởng đến luồng công nhân không?
Anthony Kong


0

Có một vấn đề chung: thật khó để chế nhạo thời gian. Ngoài ra, thực sự không tốt khi đặt mã chạy / chờ lâu trong bài kiểm tra đơn vị.

Vì vậy, để làm cho một API lập lịch có thể kiểm tra được, tôi đã sử dụng một giao diện có triển khai thực và giả như thế này:

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);
    }

}

Với điều này, bạn có thể bắt chước thời gian trong bài kiểm tra của mình:

@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"));
}

Tất nhiên, một giả lập đa luồng nâng cao cho Clockphức tạp hơn nhiều, nhưng bạn có thể tạo ra nó với các ThreadLocaltham chiếu và một chiến lược đồng bộ hóa thời gian tốt, chẳng hạn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.