Весенние Испытания :транзакция не откатывается после выполнения тестового метода
-
20-09-2019 - |
Вопрос
Я пытаюсь создать интеграционные тесты для устаревшего приложения, развернутого на Weblogic 8.1, используя подкласс AbstractTransactionalJUnit4SpringContextTests.
Мой метод тестирования имеет следующие примечания :
@Test
@Rollback(true)
public void testDeployedEJBCall throws Exception {...}
Мой тестовый класс также ссылается на компоненты типа org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean, который прокси-сервер EJBS, развернутый на моем сервере weblogic.
Когда я последовательно вызываю методы этого прокси-компонента в своем тестовом методе, транзакция корректно откатывается в конце теста.
например ,:
@Test
@Rollback(true)
public void testDeployedEJBCall throws Exception {
Long result1 = myejb.method(100L);
Long result2 = myejb.method(200L);
...
}
Однако я хотел бы выполнить 2 параллельных вызова одного и того же метода EJB.Поэтому я создал внутренний класс, который реализует 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;
}
}
Есть ли способ сделать этот откат ???
Спасибо за вашу помощь.
С уважением,
Филипп
Решение
Не автоматически, нет.Проблема в том, что два дополнительных потока не участвуют в транзакции, следовательно, их действия не откатываются.
Какова цель двух параллельных исполнений?Вряд ли вы сможете протестировать проблемы с параллелизмом при таком подходе, если это то, к чему вы стремитесь.
Редактировать: Проблема в том, что тестирование на наличие проблем с параллелизмом очень сложно, потому что ваши тесты в лучшем случае вероятностны – успех или неудача зависят от тонких временных проблем, которые могут проявиться только при миллиардном запуске.Видишь эта статья на стороне сервера для хорошего изложения основ.
Эмпирическое правило должно заключаться в том, чтобы по возможности избегать ручного кодирования потоков, поскольку это трудно сделать правильно и сложно протестировать.Если вы можете, избегайте совместного состояния между потоками, а если обойти это невозможно, полагайтесь на параллельные структуры данных и асинхронных исполнителей из java.util.concurrent
посылка.