스프링 테스트 : 테스트 방법 실행 후 트랜잭션이 롤백되지 않음
-
20-09-2019 - |
문제
AbstractTransactionalJunit4SpringContextTests의 서브 클래스를 사용하여 WebLogic 8.1에 배포 된 레거시 응용 프로그램에 대한 통합 테스트를 만들려고합니다.
내 테스트 방법에는 다음과 같은 주석이 있습니다.
@Test
@Rollback(true)
public void testDeployedEJBCall throws Exception {...}
내 테스트 클래스는 또한 org.springframework.ejb.access.simpleremotestatementsessessessessessessessessessessessessesssectyfactorybean의 bean을 참조합니다.
테스트 방법 에서이 프록시 콩의 메소드를 시퀀싱 방식으로 호출하면 트랜잭션이 테스트가 끝날 때 올바르게 롤백됩니다.
예 :
@Test
@Rollback(true)
public void testDeployedEJBCall throws Exception {
Long result1 = myejb.method(100L);
Long result2 = myejb.method(200L);
...
}
그러나 동일한 EJB 메소드에 2 개의 병렬 호출을하고 싶습니다. 그러므로 나는 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;
}
}
이 롤백을 만드는 방법이 있습니까 ???
당신의 도움을 주셔서 감사합니다.
문안 인사,
필립
해결책
자동으로는 아닙니다. 문제는 두 개의 추가 스레드가 거래에 참여하지 않으므로 그들의 행동은 롤백하지 않는다는 것입니다.
두 개의 병렬 실행의 목적은 무엇입니까? 이 접근법의 동시성 문제를 테스트 할 수는 없을 것입니다.
편집하다: 문제는 동시성 문제에 대한 테스트가 매우 어렵다는 것입니다. 테스트는 기껏해야 확률 론적이기 때문에 성공 또는 실패는 10 억의 실행에만 표면적 일 수있는 미묘한 타이밍 문제에 달려 있습니다. 보다 이 서버 사이드 기사 기본 사항에 대한 좋은 요약.
경험의 규칙은 올바르게 잡기가 어렵고 테스트하기가 어렵 기 때문에 가능할 때마다 손 코드 스레딩을 피하는 것입니다. 가능하다면 스레드 사이의 공유 상태를 피하고 그 주위에 방법이 없다면 동시 데이터 구조와 비동기적 인 집행자에게 의존하십시오. java.util.concurrent
패키지.