Я предпочитаю макетирование TransactionManager
и SpringTransactionPolicy
в тесте JUnit вместо удаления поведения транзакции из маршрута.
Вы можете использовать для этого мой служебный класс:
import org.apache.camel.impl.JndiRegistry;
import org.apache.camel.spring.spi.SpringTransactionPolicy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.*;
import org.springframework.transaction.support.*;
import javax.naming.NamingException;
import javax.transaction.TransactionManager;
import java.lang.reflect.Field;
public class TransactionalMock {
private static final Logger LOG = LoggerFactory.getLogger(TransactionalMock.class);
public static void register(JndiRegistry registry) throws NamingException {
AbstractPlatformTransactionManager transactionManager = new AbstractPlatformTransactionManager() {
@Override
protected Object doGetTransaction() throws TransactionException {
return null;
}
@Override
protected void doBegin(Object o, TransactionDefinition transactionDefinition) throws TransactionException {
LOG.info("doBegin {}, {}", o, transactionDefinition);
}
@Override
protected void doCommit(DefaultTransactionStatus defaultTransactionStatus) throws TransactionException {
LOG.info("doCommit {}", defaultTransactionStatus);
}
@Override
protected void doRollback(DefaultTransactionStatus defaultTransactionStatus) throws TransactionException {
LOG.info("doRollback {}", defaultTransactionStatus);
}
};
//transactionManager.setNestedTransactionAllowed(true);
unbindType(registry, TransactionManager.class);
replaceBean(registry, "transactionManager", transactionManager);
for (Field propagation: TransactionDefinition.class.getFields()){
if (propagation.getName().startsWith(DefaultTransactionDefinition.PREFIX_PROPAGATION)){
SpringTransactionPolicy springTransactionPolicy = new SpringTransactionPolicy();
springTransactionPolicy.setTransactionManager(transactionManager);
springTransactionPolicy.setPropagationBehaviorName(propagation.getName());
replaceBean(registry, propagation.getName(), springTransactionPolicy);
}
}
}
private static void replaceBean(JndiRegistry registry, String name, Object bean) throws NamingException {
if (registry.lookupByName(name) != null){
registry.getContext().unbind(name);
}
registry.bind(name, bean);
}
private static void unbindType(JndiRegistry registry, Class<?> type) throws NamingException {
for (String name: registry.lookupByType(type).keySet()){
registry.getContext().unbind(name);
}
}
}
Примериспользование регистра TransactionalMock #:
public class TransactionalMockTest extends CamelTestSupport {
@Override
protected RoutesBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:transacted")
.transacted()
.to("mock:transacted");
from("direct:required")
.transacted("PROPAGATION_REQUIRED")
.to("mock:required");
from("direct:requiresNew")
.transacted("PROPAGATION_REQUIRES_NEW")
.to("mock:requiresNew");
}
};
}
@Override
protected JndiRegistry createRegistry() throws Exception {
JndiRegistry registry = super.createRegistry();
TransactionalMock.register(registry);
return registry;
}
@Test
public void testTransacted() throws Exception{
MockEndpoint mockEndpoint = getMockEndpoint("mock:transacted");
template.sendBody("direct:transacted","");
mockEndpoint.setExpectedCount(1);
mockEndpoint.assertIsSatisfied();
}
@Test
public void testTransactedRequired() throws Exception{
MockEndpoint mockEndpoint = getMockEndpoint("mock:required");
template.sendBody("direct:required","");
mockEndpoint.setExpectedCount(1);
mockEndpoint.assertIsSatisfied();
}
@Test
public void testTransactedRequiresNew() throws Exception{
MockEndpoint mockEndpoint = getMockEndpoint("mock:requiresNew");
template.sendBody("direct:requiresNew","");
mockEndpoint.setExpectedCount(1);
mockEndpoint.assertIsSatisfied();
}
}