2010-01-14 103 views
1

我正嘗試使用AbstractTransactionalJUnit4SpringContextTests的子類爲部署在Weblogic 8.1上的舊應用程序創建集成測試。春季測試:執行測試方法後未回滾的事務

我的測試方法有以下注釋:

@Test 
@Rollback(true) 
public void testDeployedEJBCall throws Exception {...} 

我的測試類還引用類型org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean,其代理EJB的部署我在WebLogic Server上的豆子。

當我在測試方法中以順序方式調用此代理bean上的方法時,事務在測試結束時正確回滾。

例如:

@Test 
@Rollback(true) 
public void testDeployedEJBCall throws Exception { 
    Long result1 = myejb.method(100L); 
    Long result2 = myejb.method(200L); 
    ... 
} 

但是,我想對同一個EJB方法進行2個並行調用。因此,我創建了一個實現Callable的內部類,以便在2個不同的線程中調用我的方法,並希望並行運行這些方法。
但是,這樣做似乎使ejb方法在我的事務之外被調用,並且沒有任何回滾。

下面是當我並行運行的方法調用的全部測試類想什麼:

import org.springframework.test.annotation.*; 

@RunWith(SpringJUnit4ClassRunner.class) 
@Transactional 
@ContextConfiguration(locations = {"classpath:path/to/tests-config.xml"}) 
@TransactionConfiguration(defaultRollback=true) 
public final class IntegrationTests extends AbstractTransactionalJUnit4SpringContextTests { 
    @Autowired 
    protected JndiTemplate jndiTemplate; 
    @Resource 
    protected Proxy myEJB; 

    public IntegrationTests() { 
     super(); 
     this.logger = Logger.getLogger(IntegrationTests.class); 
    } 

    @Test 
    @Rollback(true) 
    public void testDeployedEJBCall() throws Exception { 
     // Create a thread pool for parallel execution. 
     ExecutorService exec = Executors.newFixedThreadPool(2); 

     // Prepare the tasks for parallel execution 
     List<CallEJBTask> tasks = new ArrayList<CallEJBTask>(); 
     tasks.add(new CallEJBTask(100L, this.myEJB)); 
     tasks.add(new CallEJBTask(200L, this.myEJB)); 

     // Execute all pending tasks in the exec Threadpool 
     List<Future<Long>> results = exec.invokeAll(tasks); 

     // Get the results of each task 
     Long result1 = results.get(0).get(); 
     Long result2 = results.get(1).get(); 

     ... 
    } 
} 

private class CallEBJTask implements Callable<Long> { 
    private final Long valueToTest; 
    private final MyEJB myEJB; 

    public CallEJBTask(Long valueToTest, Proxy myEJBProxy) 
     this.valueToTest = valueToTest; 
     this.myEJB = (MyEJB)myEJBProxy; 
    } 

    public Long call() throws Exception { 
     return getResult(); 
    } 

    public Long getResult() { 
     Long result = null; 

     try { 
      result = this.myEJB.method(this.patient); 

     } catch (Exception e) { 
      ... 
     } 
     return result; 
    } 
} 

有沒有一種方法,使這項回滾???

感謝您的幫助。

問候,

菲利普

回答

2

不能自動,沒有。問題是兩個額外的線程不參與事務,因此他們的操作不會回滾。

這兩個並行執行的目的是什麼?如果這是你的目標,你將不可能測試這種方法的併發性問題。

編輯:的問題是,測試併發問題是非常困難的,因爲你的測試,充其量概率 - 成功或失敗取決於微妙的時機問題,可能僅在十億運行表面。請參閱this Serverside article以獲得基礎知識的完整摘要。

經驗法則應儘可能避免手動編碼線程,因爲它很難正確且難以測試。如果可以的話,避免在線程之間共享狀態,並且如果沒有辦法繞過它,則依靠java.util.concurrent包中的併發數據結構和異步執行程序。

+0

是的,這正是我的目標......我應該用什麼方法呢? 我想過的另一種可能性是在我的測試方法的頭文件中使用@Repeat(someBigNumber)在兩臺不同的機器上運行相同的測試......這樣工作嗎? – Philippe 2010-01-14 13:32:39

+0

嗯......我看過那篇文章......不是我在我的例子中正在做的事情嗎? – Philippe 2010-01-15 13:23:32