有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

多线程如何使用Java并发执行器为代码编写junit测试用例(多线程)

我是多线程新手,有下面的示例代码。我们如何编写具有最大代码覆盖率的单元测试用例

public class jobExecutorImpl<T> implements jobExecutor<T>
{

    private AcquisitionProcessor processor;
    private ExecutorService jobExecutor;
    private AcquisitionProcessExecutor executorService;

    @Override
    public AcquisitionResponse<T> processContent(Collection<T> itemsToProcess) throws Exception {
        AcquisitionResponse<T> acquisitionResponse = new AcquisitionResponse<>();
        if(CollectionUtils.isNotEmpty(itemsToProcess)){

          //  List<Callable<T>> tasks = new ArrayList<Callable<T>>();
           // CountDownLatch latch=new CountDownLatch(itemsToProcess.size());
            LOGGER.info("Items to Process: "+itemsToProcess.size());
            for (T item : itemsToProcess) {

                jobExecutor.execute(new Runnable() {
                    @Override
                    public void run() {
                        AcquisitionStatus status= null;
                        try {
                            status = executorService.process(item);
                        } catch (Exception e) {
                            e.printStackTrace();
                            //TODO catch filenotfound and throw
                        }
                        if(status!=null) {

                            acquisitionResponse.addStatus(item, status);
                        }
                    }

                });
              //  tasks.add(new threadExecutor(item,acquisitionResponse,latch));

            }
           // jobExecutor.invokeAll(tasks);


        }
        processor.archiveFile();
        return acquisitionResponse;
    }





// actually code processed in each thread

public class ProcessExecutor<T>
{

    private AcquisitionPreProcessor preProcessor;
    private AcquisitionProcessor processor;
    private Converter requestConverter;
    private Converter responseConverter;
    private MediaManagementService mediaManagementService;
    private ContentComparator contentComparator;
    private MediaContentDAO mediaContentDao;


     public AcquisitionStatus process(T item) throws Exception
    {
        LOGGER.debug("Processing for Id: " + item.toString()+"Thread: "+Thread.currentThread().getName());
        Object response = null;
        try {
            response = processor.processInternal(requestConverter.convert(item));
            List<MediaContent> targetList = ((SupplierContent) responseConverter.convert(response)).getMediaContents();
            if(CollectionUtils.isNotEmpty(targetList)){
                List<MediaContent> sourceList = mediaContentDao.getAllParentMediaContentsByLobTypeAndValue(targetList.get(0).getContentLobValue(),  targetList.get(0).getContentLOBType());
                List<MediaContent> listOfComparedMediaContents = contentComparator.compare(sourceList,targetList);
                int insertCount = 0,deleteCount = 0;
                for(MediaContent mediaContent:listOfComparedMediaContents){
                    if(mediaContent.getActionType().equals(ActionType.DELETE)){
                        LOGGER.info("Processing delete");
                        mediaManagementService.deleteContent(mediaContent);
                        deleteCount = deleteCount + getNumOfMediaContents(mediaContent);
                    }
                    if(mediaContent.getActionType().equals(ActionType.INSERT)){
                        LOGGER.info("Processing insert");
                        mediaManagementService.insertContent(mediaContent);
                        insertCount = insertCount + getNumOfMediaContents(mediaContent);
                    }
                }
                if(deleteCount + insertCount > 0){
                   return new AcquisitionStatus(StatusType.Processed, insertCount, deleteCount);
                }
            }
        }catch(FileNotFoundException e)
        {
            throw e;
        }
        catch(Exception e) {

            handleException(item, e);
            return new AcquisitionStatus(StatusType.Error, e);
        }
        return null;
    }

共 (2) 个答案

  1. # 1 楼答案

    public class JobExecutorImplTest {
        @Test
        public void testItemsProcessedConcurrently() {
            /*
            1) There is a CountDownLatch processingStarted = new CountDownLatch(2);
            2) initialize jobExecutorImpl with:
                - fixed-thread pool (2 threads) Executors.newFixedThreadPool(2)
                - MockExecutorService
            3) MockExecutorService does following in it's process method:
                - processingStarted.countDown();
                - processingStarted.await()
            4) Run processing: jobExecutorImpl.processContent()
            5) wait in test that processing of all items has been started: processingStarted.await()
            */
        } 
    }
    
  2. # 2 楼答案

    匿名类很难进行单元测试。 如果代码部分的复杂性最低,我不会使用匿名类,原因如下:

    查看您的代码:

    jobExecutor.execute(new Runnable() {
    

    如果你想改变这一点,这个新的Runnable()就是个问题。 相反,要定义一个匿名类,可以定义一个普通类,例如内部类(例如AquisitionExecutor),并传递一个新实例来执行。 然而,在你的情况下,这似乎不是必要的。在你的例子中,匿名类并不是那么复杂。我可以相信它不会被单元测试所转移

    多线程代码不容易进行单元测试。确保单元测试不会在线程终止之前终止。并在线程完成工作后检查预期结果

    我通过定义一个ITarget接口来实现这一点,代码使用该接口来转发计算结果。在单元测试的情况下,我用实现ITarget的testCaseClass替换该目标实例