2

I have a default Java EE 7 application with JPA/Eclipselink. I want to write some UI tests with Arquillian Drone/Graphene.

My testsuite is "working". I can click through the application and make some asserts.

But: I want to create multiple tests. Every test class should reset the database, to make sure, that the conditions are always the same.

I'm using flyway to reset my database.

@Before
public void setup() {
 Flyway flyway = new Flyway();
 flyway.setDataSource(...);
 flyway.clean();
 flyway.init();
 flyway.migrate();
}

The reset is working. And the first execution of the test also (at this situation, nothing is in any cache). When I try to execute the test again, the database is inconsistent with strange JPA errors. First I thought ok: Reset the cache

getEntityManager().getEntityManagerFactory().getCache().evictAll();

Is not enough. Same problems. Next idea was to destroy the sessions (Some JPA data could be saved in old sessions). I haven't found a good way to destroy all sessions. I made a workaround, but this doesn't work also.

I think I have a default problem, but I can not found any solutions for this problem.

I also tried dbunit and the arquillian-persistence-extension. But it is like flyway, just another way.

In theory the problem is, that the database has been reset manually over SQL and Java/JPA/EclipseLink/The Sessions/deployed applaction have no idea about the changed data. How can I reset everything (all Caches?)?

I also thought about "redeploy before start testclass". But this is a little bit to much (takes more time and is no fine solution)?

One more information: I'm also doing normal arquillian-tests (without UI/Selenium), here is my flyway database reset working.

Thanks for help :).

  • Maybe start by posting the strange JPA problems, as they are unexpected and might point to a different root cause. Also, are you holding onto the same EntityManager or obtaining a new one per test? – Chris Nov 26 '14 at 14:25
  • One error is for example: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint »abstractentity_pkey« Detail: key »(id)=(29420)« exists already sequence/seq_count has the right value in the database. It must be sth. in some cache. – user3263327 Nov 27 '14 at 07:59
  • In my testsuite I have no entity manager (I'm using a jdbc connection to reset it). In my app I have @PersistenceContext(unitName = "mydatabasePU") private EntityManager em; I think the persistence context is created per usersession. I can not reuse the context in the testsuite? – user3263327 Nov 27 '14 at 08:11

1 Answers1

1

You didn't say what errors you really got, you just said:

When I try to execute the test again, the database is inconsistent with strange JPA errors (...)

It is hard to believe that your problem lies in JPA cache. I think that your problem has totally different source.

Your approach to cleaning the database has a fundamental flaw. Code that you've presented: should be run only once, before all tests. Because Flyway is meant to prepare the database structure, not to setup it into known state.
So conceptually DbUnit & Arquillian Persistence Extension and Flyway do two really different things. They are not a replacement for each other.

So your code that uses flyway:

@Before
public void setup() {
 ...
  flyway.clean();
  flyway.init();
  flyway.migrate();
}

is wrong, because it should be run only once before all tests. To do that you can use some container features:

  1. If using EJB Container, then @Singleton + @Startup + @PostConstruct combination could be used to launch flyway tool.
  2. If using Spring Container, then init-method="migrate" would do the trick.
  3. Or use maven and its pre-integration-test phase to launch flyway tool.

By the way: to avoid maintenance effort associated with DbUnit's xml datasets, personally I would recommend DbSetup tool. Nice and simple solution.

Edit

Besides the fact, that changing the DB structure during tests isn't a good practice - your problem may also be caused that both Flyway and JPA are using different datasources (even pointing to the same DB). You should double check that you're not creating DataSource on your own - just inject for the Flyway the same one that PersistenceUnit is using.

halfer
  • 19,824
  • 17
  • 99
  • 186
G. Demecki
  • 10,145
  • 3
  • 58
  • 58
  • I can also use @BeforeClass, this is running before all tests in class are executed. Only once. But the errors are the same. all reset tools are working with an extra jdbc connection. The Java application does not know anything about a database change. What I need is: How can I tell the app, that the database has been changed and everything should be refreshed/reset? – user3263327 Nov 27 '14 at 08:03
  • Not exactly, @BeforeClass is launched before each test class - so it's still too much. I don't know why on earth, you are changing the whole database structure during tests. It's not a good practice. – G. Demecki Nov 27 '14 at 08:54
  • I have multiple UI test classes. Every UI test class should start with the same clean situation, because Test1 is creating some data which would conflict Test2. So I want to reset the database for every class. To remove every new data after one testclass is a complex topic. One testclass is creating a lot of database entries (250-500 entries in multiple tables with a lot of constraints) I thought that the flyway sql dump reset is the easiest way to create a clean database. – user3263327 Nov 27 '14 at 09:12
  • Recreating the database is different from removing all records from the all tables. Please consider the latter one (DbSetup or Arquillian Persistence Extension then may be useful). – G. Demecki Nov 27 '14 at 10:25
  • 2
    setting the same datasource is working. @Resource(lookup = "mydatasource") private DataSource dataSource; flyway.setDataSoruce(dataSource); Thank you for help – user3263327 Nov 27 '14 at 10:39