OSDir


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Unit testing simple JPA route


Hello,

I've spent a long time with this so this request is a bit of a last resort.

I have a very simple route:
@Component
public class IngestRouteBuilder extends RouteBuilder {

    @Override
    public void configure() throws Exception {

from("seda:ingest_database_queue?concurrentConsumers={{seda.ingest.concurrent.consumers}}")
            .routeId("ingest-database-persisting")
            .to("jpa:esac.archive.p2sa.ingest.entity.ingest.IngestLog")
            .log(LoggingLevel.INFO, "Finished Inserting IngestLog")
            .bean(MessageBodySetterBean.class)
.recipientList(simple("file://${headers.FileDestination}/?fileName=${headers.Filename}")) .log(LoggingLevel.INFO, "Finished Ingesting File: ${headers.Filename}}");

    }

}

Which persists an entity to the database and moves a file somewhere.

My idea was to make use of @DataJpaTest which loads up all the in memory database etc for unit tests and it nearly works.

This is my test (sorry to paste large code):
@RunWith(SpringRunner.class)
@DataJpaTest
//@Transactional(propagation = Propagation.NOT_SUPPORTED)
public class IngestRouteBuilderTest extends CamelTestSupport {

    @Autowired
    private TestEntityManager entityManager;

    private static final String TARGET_DIR = "target/repository";
    @Override
    public void setUp() throws Exception {
        deleteDirectory(TARGET_DIR);
        super.setUp();
    }

    @Override
    public void tearDown() throws Exception {
        deleteDirectory(TARGET_DIR);
        super.tearDown();
    }

    @Override
    public String isMockEndpoints() {
// override this method and return the pattern for which endpoints to mock.
        return "file:" + TARGET_DIR + "*";
    }

    @Test
    public void testDeadLetterChannel() throws Exception {


        // This is a notify wait condition
NotifyBuilder notify = new NotifyBuilder(context).from("seda:*").whenDone(1).create();

// notice we have automatic mocked all endpoints and the name of the endpoints is "mock:uri" MockEndpoint mock = getMockEndpoint("mock:file:" + TARGET_DIR + "/");
        mock.expectedMessageCount(1);

        // Mock the headers
        Map<String, Object> headers = new HashMap<>();
headers.put(Constants.FILE_NAME_HEADER, "lyra_20160708-000000_lev1_met.fits");
        headers.put(Constants.FILE_CONTENT_HEADER,
TestUtils.getFile("/data/lyra/level1/lyra_20160708-000000_lev1_met.fits"));

        // Setup the exchange
        Exchange exchange = new DefaultExchange(context);
        exchange.getOut().setHeaders(headers);

        exchange.getIn().setBody(createIngestLog());

        // Send the message
        template.send("seda:ingest_database_queue", exchange);

        //unwrap.getSession().beginTransaction().begin();

        // Verify the outcome
        assertMockEndpointsSatisfied(5, TimeUnit.SECONDS);
        boolean done = notify.matches(5, TimeUnit.SECONDS);
        assertTrue("Should be done", done);
assertTrue("File should exist", new File("target/failed-test/lyra_20160708-000000_lev1_met.fits").exists());
    }

    @Override
protected Properties useOverridePropertiesWithPropertiesComponent() {
        Properties extra = new Properties();
        extra.put("seda.ingest.concurrent.consumers", "1");
        return extra;
    }

    @Override
    protected RouteBuilder createRouteBuilder() throws Exception {
JpaComponent component = (JpaComponent)context.getComponent("jpa"); component.setEntityManagerFactory(entityManager.getEntityManager().getEntityManagerFactory());

//Map<String, Object> properties = entityManager.getEntityManager().getProperties(); //EntityManagerFactory createEntityManagerFactory = javax.persistence.Persistence.createEntityManagerFactory("camel", properties);
        //component.setEntityManagerFactory(createEntityManagerFactory);


        IngestRouteBuilder route = new IngestRouteBuilder();
//ReflectionTestUtils.setField(route, "failed", "file:target/failed-test");
        return route;
    }

    private IngestLog createIngestLog() {
        IngestLog ingestLog = new IngestLog();
        ingestLog.setStatus(IngestStatus.INGEST_DONE.name());
        ingestLog.setDataType(DataType.SCIENCE.name());

Instant ingested = Instant.from(Instant.now().atOffset(ZoneOffset.UTC));
        ingestLog.setDateIngested(Date.from(ingested));
        ingestLog.setFileFormat(FileExtension.FITS.name());

        ingestLog.setFileName("filename");
        ingestLog.setFileSize(500);
        ingestLog.setPathStage("/stage/path");
        ingestLog.setPathRepository("/final/path");
        return ingestLog;
    }
}

It fails with the following error:
2018-04-10 17:37:19 WARN o.a.c.component.seda.SedaConsumer - Error processing exchange. Exchange[]. Caused by: [javax.persistence.TransactionRequiredException - no transaction is in progress] javax.persistence.TransactionRequiredException: no transaction is in progress at org.hibernate.internal.SessionImpl.checkTransactionNeeded(SessionImpl.java:3430)
	at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1397)
	at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1393)
at org.apache.camel.component.jpa.JpaProducer$2.doInTransaction(JpaProducer.java:247) at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133) at org.apache.camel.component.jpa.JpaProducer.processEntity(JpaProducer.java:210) at org.apache.camel.component.jpa.JpaProducer.process(JpaProducer.java:162) at org.apache.camel.util.AsyncProcessorConverterHelper$ProcessorToAsyncProcessorBridge.process(AsyncProcessorConverterHelper.java:61)
...

I'm not really interested in transactions, however if I uncomment this at the top //@Transactional(propagation = Propagation.NOT_SUPPORTED) then I get a different failure - java.lang.IllegalStateException: No transactional EntityManager found.

If I remove the test entity manager then I get the following error:\
endpoint: jpa://esac.archive.p2sa.ingest.entity.ingest.IngestLog. Reason: javax.persistence.PersistenceException: No Persistence provider for EntityManager named camel

I looked at some of the tests in the component and I don't see what I'm doing differently really.

Thanks
Jonathan