2015-11-13 30 views
0

我是新來的多線程並具有下面的示例代碼。我們如何編寫最大代碼覆蓋率的單元測試用例?如何使用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; 
    } 
+0

另請參見https://stackoverflow.com/questions/12159/how-should-i-unit-test-threaded-code – Raedwald

回答

0

匿名類很難進行單元測試。 如果代碼部分有一個最低的複雜性,我不使用匿名類是原因:

看到你的代碼:

jobExecutor.execute(new Runnable() { 

這個新的Runnable()是一個問題,如果你想CONVER這一點。 而不是定義一個匿名類,你可以定義一個普通的類,例如一個內部類(例如AquisitionExecutor),並傳遞一個新的實例來執行。 在你的情況下,這似乎不是必要的。你的案例中的匿名類不是那麼複雜。我可以活下去,它不會受到單元測試的影響。

多線程代碼不容易進行單元測試。確保在線程終止之前單元測試沒有終止。並在線程完成工作後檢查預期結果。

我通過定義代碼使用的ITarget接口來轉發他們的計算結果。在單元測試的情況下,我將該目標實例替換爲實現ITarget的testCaseClass。

0
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() 
     */ 
    } 
} 
相關問題