jeudi 14 février 2019

h2 database access to test data from separate threads

My Integration Test scenario:

  1. create a row in H2 database
  2. sleep(50000ms) (in the meantime another thread is invoked thanks to spring configuration and this thread should find row created in point 1. and update this row)
  3. expect a row from point 1. has been updated by thread mentioned in point 2.

This scenario tests both - the configuration & implementation. And this is what I want to achieve.

I am using H2 database in all my tests so decided to use it here as well. When debugging the test scenario I discovered that new thread invoked during sleep - connects to the DB but doesn't find the row created. I went through H2 documentation and I started using:

java -cp ~/.m2/repository/com/h2database/h2/1.4.194/h2-1.4.194.jar org.h2.tools.Server -tcp -web -browser -tcpAllowOthers -tcpPort 9092 -webPort 8082

and the connection string:

DB_URL=jdbc:h2:tcp://localhost:9092/~/test2

and the config:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
      destroy-method="close" p:driverClassName="org.h2.Driver"
      p:url="${DB_URL}"
      p:username="${OPENSHIFT_MYSQL_DB_USERNAME}" p:password="${OPENSHIFT_MYSQL_DB_PASSWORD}"/>

<util:properties id="hibernateProperties">
    <prop key="hibernate.dialect">org.hibernate.dialect.H2Dialect</prop>
    <prop key="hibernate.hbm2ddl.auto">validate</prop>
    <prop key="hibernate.show_sql">false</prop>
</util:properties>

<bean id="sessionFactory"
      class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"
      p:dataSource-ref="dataSource" p:packagesToScan="com.fridayweekend.lottery.model"
      p:hibernateProperties-ref="hibernateProperties"/>

<bean id="transactionManager"
      class="org.springframework.orm.hibernate5.HibernateTransactionManager"
      p:sessionFactory-ref="sessionFactory"/>

NOTE: I already played a bit with ddl-auto - I tried to create schema at firs dry-run and then only validate it (to preven re-creation) but it didn't helped.

I can inspect the database via H2 Web Console. I see that the Schema is created (based on my Java-annotated Model), but no data is there (even during sleep or during debug breakpoint).

On the other hand - when I add the data (from the 1st scenario point) manually - I can debug that the second thread see it and update it correctly, then the test succeed. Data originated from the second thread is persisted and I can see it even after test suite finishes.

What should I do that the data originated from the main (@Test-annotated) thread be visible to the second thread?

PS. I think this is not relevant, but the "second" thread is invoked like that:

    <util:properties id="javaMailProperties">
    <prop key="mail.imap.socketFactory.class">javax.net.ssl.SSLSocketFactory</prop>
    <prop key="mail.imap.socketFactory.fallback">false</prop>
    <prop key="mail.store.protocol">${imap.protocol}</prop>
    <prop key="mail.debug">${imap.debug}</prop>
</util:properties>
<mail:inbound-channel-adapter id="imapAdapter"
                              store-uri="${imap.uri}"
                              channel="recieveEmailChannel"
                              should-delete-messages="false"
                              should-mark-messages-as-read="true"
                              auto-startup="true"
                              java-mail-properties="javaMailProperties">
    <int:poller fixed-delay="${imap.poolerSecondsDelay}" time-unit="SECONDS"/>
</mail:inbound-channel-adapter>
<int:channel id="recieveEmailChannel">
    <int:interceptors>
        <int:wire-tap channel="logger"/>
    </int:interceptors>
</int:channel>
<int:logging-channel-adapter id="logger" level="DEBUG"/>
<int:service-activator input-channel="recieveEmailChannel" ref="emailReceiverService" method="receive"/>

so basicaly - it calls method receive of emailReceiverService bean. Of course - I ensured that the method is invoked (by sending an email to the inbox) - but, as I said- I do not think that the way the second thread is being created is relevan. Basically speaking - it is invoked by Spring configuration (spring configuration is passed to test method via @ContextConfiguration(locations = { "classpath:spring/test-lottery-context.xml", "classpath:spring/test-sms-context.xml" })).

Aucun commentaire:

Enregistrer un commentaire