2014-04-17 42 views
0

我的客戶要我寫了系統的測試性能的測試。但我有實體經理的問題。 我在業務有一個方法:JUnit測試多線程和實體管理器無法正常工作

@Transactional(isolation = Isolation.READ_COMMITTED) 
public ProductSequence generate(String prefix) { 
    if (StringUtils.isBlank(prefix)) { 
     throw new IllegalArgumentException("prefix is blank"); 
    } 
    ProductSequence productSequence = new ProductSequence(); 
    List<ProductSequence> lstProductSequences = getProductSequenceByPrefix(prefix); 

    if (!lstProductSequences.isEmpty()) { 
     productSequence = lstProductSequences.get(0); 
     productSequence.setSequence(productSequence.getSequence() + 1); 
     this.entityManager.merge(productSequence); 

    } else { 
     productSequence.setPrefix(prefix); 
     productSequence.setSequence(1L); 
     this.entityManager.persist(productSequence); 
//want to check again if data was persisted or not 
     List<ProductSequence> lstProductSequences2 = getProductSequenceByPrefix(prefix); 
     if (lstProductSequences2.isEmpty()) { 
      System.out.println("cannt persist entity manager"); 
     } 

    } 
    return productSequence; 

} 

/** 
* get product list by prefix. 
* 
* @param prefix 
*   <code>String</code> 
* @return List<ProductSequence> 
*/ 
@Transactional 
public List<ProductSequence> getProductSequenceByPrefix(String prefix) { 
    TypedQuery<ProductSequence> typedQuery = entityManager.createQuery(
      "SELECT o FROM ProductSequence AS o WHERE o.prefix = :prefix", ProductSequence.class); 

    typedQuery.setParameter("prefix", prefix); 
    return typedQuery.getResultList(); 
} 

這裏是這些方法

final String prefix = "TEST-AUTO"; 
final List<String> tags = new LinkedList<String>(); 
@Test 
public void testGenerateWithThread() { 



    final int loops = 5; 

    final int threadCount = 1; 

    final CyclicBarrier barrier = new CyclicBarrier(threadCount + 1); 

    final boolean[] error = new boolean[] { false }; 

    Thread[] threads = new Thread[threadCount]; 
    for (int i = 0; i < threads.length; i++) { 
     final int t = i; 
     Runnable r = new Runnable() { 
      @Override 
      @Transactional 
      public void run() { 
       try { 
        barrier.await(); 
       } catch (InterruptedException e) { 
        error[0] = true; 
       } catch (BrokenBarrierException e) { 
        error[0] = true; 
       } 
       for (int j = 0; j < loops; j++) { 
        String tagGenerate = productSequence.generate(prefix); 
        tags.add(tagGenerate); 
        System.out.println("In thread " + t + ": " + tagGenerate); 
       } 
      } 
     }; 
     threads[i] = new Thread(r); 
     threads[i].start(); 
    } 

    try { 
     barrier.await(); 
    } catch (InterruptedException e1) { 
     System.out.println("Interrupted whilst waiting for barrier"); 
    } catch (BrokenBarrierException e1) { 
     System.out.println("Broken barrier"); 
    } 

    for (int i = 0; i < threads.length; i++) { 
     try { 
      threads[i].join(); 
     } catch (InterruptedException e) { 
      System.out.println("Interrupted whilst joining thread " + i); 
     } 
    } 

    assertEquals(threadCount * loops, tags.size()); 
} 

/** 
* test for generate function 
*/ 
@Test 
@Transactional 
public void testGenerateWithoutThread() { 
    for (int i = 1; i <= 5; i++) { 
     String tagGenerate = productSequence.generate(prefix); 
     System.out.println("tag gen " + tagGenerate); 
     assertEquals(prefix + "-" + i, tagGenerate); 
    } 
} 

問題是,當測試運行,testGenerateWithoutThread方法工作正常,但testGenerateWithThread cannt持久化數據到內存的測試方法數據庫。運行testGenerateWitThread當標籤列表中的所有值是 「TEST-AUTO-1」,但在testGenerateWithoutThread將 「TEST-AUTO-1」, 「TEST-AUTO-2」, 「TEST-AUTO-3」,「TEST-AUTO -4「,」TEST-AUTO-5「。 我不知道爲什麼?當我運行多線程測試時,實體管理器不能將數據保存到內存數據庫中,但正常的方式可以嗎?

請幫幫我!非常感謝 !

+0

由於線程版本只是在循環中執行日誌記錄,因此它在第二到第五遍中做了什麼?是否有例外導致它退出?它掛了嗎?如果您在查詢之後但在查詢之前使用this.entityManager.flush(),會發生什麼情況? – Chris

回答

0

testGenerateWithThread()需要,因爲你有它TestGenerateWithoutThread@Transactional標籤。請嘗試以下操作:

@Test @Transactional public void TestGenerateWithThread() { 

    final int loops = 5; 

    final int threadCount = 1; 

    final CyclicBarrier barrier = new CyclicBarrier(threadCount + 1); 

    final boolean[] error = new boolean[] { false }; 

    Thread[] threads = new Thread[threadCount]; 
    for (int i = 0; i < threads.length; i++) { 
     final int t = i; 
     Runnable r = new Runnable() { 
      @Override 
      @Transactional 
      public void run() { 
       try { 
        barrier.await(); 
       } catch (InterruptedException e) { 
        error[0] = true; 
       } catch (BrokenBarrierException e) { 
        error[0] = true; 
       } 
       for (int j = 0; j < loops; j++) { 
        String tagGenerate = productSequence.generate(prefix); 
        tags.add(tagGenerate); 
        System.out.println("In thread " + t + ": " + tagGenerate); 
       } 
      } 
     }; 
     threads[i] = new Thread(r); 
     threads[i].start(); 
    } 

    try { 
     barrier.await(); 
    } catch (InterruptedException e1) { 
     System.out.println("Interrupted whilst waiting for barrier"); 
    } catch (BrokenBarrierException e1) { 
     System.out.println("Broken barrier"); 
    } 

    for (int i = 0; i < threads.length; i++) { 
     try { 
      threads[i].join(); 
     } catch (InterruptedException e) { 
      System.out.println("Interrupted whilst joining thread " + i); 
     } 
    } 

    assertEquals(threadCount * loops, tags.size()); 
} 
+0

感謝您的回覆。但我試圖把它放在testGenerateWithThread()但它不起作用。 – binhnguyen