Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/344.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用CountDownLatch对方法进行单元测试?_Java_Unit Testing_Countdownlatch - Fatal编程技术网

Java 如何使用CountDownLatch对方法进行单元测试?

Java 如何使用CountDownLatch对方法进行单元测试?,java,unit-testing,countdownlatch,Java,Unit Testing,Countdownlatch,我需要做下面的代码,这是使用countdownlatch的单元测试。这只是一个测试代码。我使用mockito,然后使用answer和invocationmask来模拟线程/callable。但我不知道如何在单元测试中初始化/模拟或退出countdownlatch public class ThreadPoolTaskExecRunner { private ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTask

我需要做下面的代码,这是使用countdownlatch的单元测试。这只是一个测试代码。我使用mockito,然后使用answer和invocationmask来模拟线程/callable。但我不知道如何在单元测试中初始化/模拟或退出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();
            }
        }
    }
}
公共类ThreadPoolTaskExecRunner{
私有ThreadPoolTaskExecutor ThreadPoolTaskExecutor=新ThreadPoolTaskExecutor();
私有ArrayBlockingQueue值=新的ArrayBlockingQueue(100,true);
公共线程池TaskExecRunner(){
threadPoolTaskExecutor.setCorePoolSize(5);
threadPoolTaskExecutor.setMaxPoolSize(10);
threadPoolTaskExecutor.SetWaitForTaskStoCompleteonShutton(true);
threadPoolTaskExecutor.setRejectedExecutionHandler(新的ThreadPoolExecutor.CallerRunPolicy());
threadPoolTaskExecutor.initialize();
}
公共静态void main(字符串参数[]){
ThreadPoolTaskExecRunner obj=新的ThreadPoolTaskExecRunner();
obj.testCountDownLatch();
}
public void testCountDownLatch(){
最终倒计时闩锁=新倒计时闩锁(5);
Future future1=threadPoolTaskExecutor.submit(新任务(“A”,值,闩锁));
Future future3=threadPoolTaskExecutor.submit(新任务(“B”,值,闩锁));
Future future4=threadPoolTaskExecutor.submit(新任务(“C”,值,闩锁));
Future future5=threadPoolTaskExecutor.submit(新任务(“D”,值,闩锁));
Future future2=threadPoolTaskExecutor.submit(新任务(“E”,值,闩锁));
试一试{
latch.await();//主线程正在等待CountDownLatch完成
}捕获(中断异常ie){
系统输出打印(ie);
}
System.out.println(“***************完成************值大小=“+values.size()”);
用于(字符串s:值)
系统输出打印项次;
threadPoolTaskExecutor.shutdown();
}
公共静态类任务实现了可调用{
私有字符串类型;
私有ArrayBlockingQueue值;
私人倒计时闩锁;
公共任务(字符串s、ArrayBlockingQueue值、CountDownLatch闩锁){
this.type=s;
这个值=值;
this.latch=闩锁;
}
@凌驾
公共字符串调用()引发异常{
试一试{
System.out.println(“内部调用类型:“+type”);
睡眠(10);
值。添加(类型);
返回类型;
}最后{
如果(闩锁!=null)
倒计时();
}
}
}
}
我开发了单元测试类,但它没有帮助

@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();
    }
}
@RunWith(MockitoJUnitRunner.class)
公共类ThreadPoolTaskExecuteRunnerTest{
@嘲弄
私有线程池taskExecutor taskExecutor;
@注射模拟
ThreadPoolTaskExecRunner ThreadPoolTaskExecRunner;
@试验
公开无效测试(){
当(taskExecutor.submit(any(ThreadPoolTaskExecRunner.Task.class))。然后回答(new-Answer(){
公共未来应答(invocationMock调用)抛出可丢弃的{
Future=mock(FutureTask.class);
when(future.isDone()).thenReturn(false,false,true);
when(future.get()).thenReturn(“这是一个测试”);
回归未来;
}
});
threadPoolTaskExecRunner.testCountDownLatch();
}
}

那么您想测试什么?我想您应该测试调用了
countDown
。所以你可以这样做:

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

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

    // evaluation
    verify(latch).countDown();
}
如果您还想在调用倒计时之前测试该值是否已添加,请使用:

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

  • 在这种特殊情况下,调用
    Future.get()
    会更容易,它也会等待任务完成
  • 给出测试方法的描述性名称,有助于理解测试内容
  • 尽量使并发性远离单元测试。大多数类不像类
    任务
    那样处理并发性。它不在乎它是否在新线程中执行,它只是碰巧在您的情况下执行。所以你可以单独测试这个类。如果你能很好地构造你的代码,你将拥有处理线程组织的类,而不是其他的类,以及执行工作的其他类。这使得分离算法测试和线程处理测试更容易,并且测试更易于阅读

    • 那么你想测试什么?我想您应该测试调用了
      countDown
      。所以你可以这样做:

      public void taskCallsCountDownOnce() {
          // setup
          final CountDownLatch latch = mock(CountDownLatch.class);
      
          // execution
          new Task("A", values, latch).call();
      
          // evaluation
          verify(latch).countDown();
      }
      
      如果您还想在调用倒计时之前测试该值是否已添加,请使用:

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

      • 在这种特殊情况下,调用
        Future.get()
        会更容易,它也会等待任务完成
      • 给出测试方法的描述性名称,有助于理解测试内容
      • 尽量使并发性远离单元测试。大多数类不像类
        任务
        那样处理并发性。它不在乎它是否在新线程中执行,它只是碰巧在您的情况下执行。所以你可以单独测试这个类。如果你能很好地构造你的代码,你将拥有处理线程组织的类,而不是其他的类,以及执行工作的其他类。这使得分离算法测试和线程处理测试更容易,并且测试更易于阅读

      您不应该测试未编写的代码。。。你有没有写过一个单元测试来测试List/Array/Integer等等?此外,您要测试的到底是什么?看起来我的方法名testCountDownLatch()让您感到困惑。我的服务需要并行执行一些任务,它应该等待所有任务完成。我用countdowlatch来做这个。现在我需要测试我的服务。P