簡體   English   中英

如何使用CountDownLatch對方法進行單元測試?

[英]How to Unit Test a method using CountDownLatch?

我需要使用countdownlatch進行以下代碼的單元測試。 這只是一個測試代碼。 我正在使用嘲笑then / Answer和InvocationOnMask模擬線程/可調用。 但是我不知道如何在單元測試中初始化/模擬或退出countdownlatch。

public class ThreadPoolTaskExecRunner {
    private ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
    private ArrayBlockingQueue<String> values = new ArrayBlockingQueue<String>(100, true);

    public ThreadPoolTaskExecRunner() {
        threadPoolTaskExecutor.setCorePoolSize(5);
        threadPoolTaskExecutor.setMaxPoolSize(10);
        threadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        threadPoolTaskExecutor.initialize();
    }

    public static void main(String args[]) {
        ThreadPoolTaskExecRunner obj = new ThreadPoolTaskExecRunner();
        obj.testCountDownLatch();
    }
    public void testCountDownLatch() {
        final CountDownLatch latch = new CountDownLatch(5);
        Future<String> future1 = threadPoolTaskExecutor.submit(new Task("A", values, latch));
        Future<String> future3 = threadPoolTaskExecutor.submit(new Task("B", values, latch));
        Future<String> future4 = threadPoolTaskExecutor.submit(new Task("C", values, latch));
        Future<String> future5 = threadPoolTaskExecutor.submit(new Task("D", values, latch));
        Future<String> future2 = threadPoolTaskExecutor.submit(new Task("E", values, latch));

        try{
            latch.await();  //main thread is waiting on CountDownLatch to finish
        }catch(InterruptedException ie){
            System.out.println(ie);
        }
        System.out.println("*********** DONE *********** values size= "+values.size());
        for(String s : values)
            System.out.println(s);
        threadPoolTaskExecutor.shutdown();
    }

    public static class Task implements Callable<String> {
        private String type;
        private ArrayBlockingQueue<String> values;
        private CountDownLatch latch;

        public Task(String s, ArrayBlockingQueue<String> values, CountDownLatch latch) {
            this.type = s;
            this.values = values;
            this.latch = latch;
        }

        @Override
        public String call() throws Exception {
            try {
                System.out.println("Inside call type: " + type);
                Thread.sleep(10);
                values.add(type);
                return type;
            } finally {
                if(latch != null)
                    latch.countDown();
            }
        }
    }
}

我開發了單元測試課程,但是它沒有幫助...

@RunWith(MockitoJUnitRunner.class)
public class ThreadPoolTaskExecRunnerTest {
    @Mock
    private ThreadPoolTaskExecutor taskExecutor;

    @InjectMocks
    ThreadPoolTaskExecRunner threadPoolTaskExecRunner;

    @Test
    public void test() {
        when(taskExecutor.submit(any(ThreadPoolTaskExecRunner.Task.class))).thenAnswer(new Answer<Future<String>>() {
            public Future<String> answer(InvocationOnMock invocation) throws Throwable {
                Future<String> future = mock(FutureTask.class);
                when(future.isDone()).thenReturn(false, false, true);
                when(future.get()).thenReturn("This is a test");
                return future;
            }
        });

        threadPoolTaskExecRunner.testCountDownLatch();
    }
}

那么您要測試什么? 我想您想測試是否調用了countDown 因此,您可以這樣做:

public void taskCallsCountDownOnce() {
    // setup
    final CountDownLatch latch = mock(CountDownLatch.class);

    // execution
    new Task("A", values, latch).call();

    // evaluation
    verify(latch).countDown();
}

如果您還想在調用countDown之前測試是否已添加了該值,請使用:

public void taskAddsValueBeforeCallingCountDown() {
    // setup & execution
    // ...
    // evaluation
    InOrder inOrder = inOrder(latch, values);
    inOrder.verify(values).add(...);
    inOrder.verify(latch).countDown();
}

一般注意事項:

  • 在這種情況下,調用Future.get()會更容易,該方法也將等待任務完成
  • 為您的測試方法提供描述性名稱,以幫助您了解正在測試的內容
  • 盡量使並發性離單元測試盡可能遠。 大多數類本身都不像您的Task那樣處理並發。 它不在乎是否在新線程中執行,只是碰巧在您的情況下。 因此,您可以單獨測試該類。 如果代碼結構良好,則將擁有處理線程組織的類,別無其他,而其他執行工作的類則別無其他。 這使得對算法的測試和對線程處理的測試更加容易分開,並且使測試更易於閱讀。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM