I've written a JEE6 application using CDI and JPA. My tests are written in JUnit. I'd like to run the database tests against an in-memory HSQLDB database in order to make sure my JPQL (which I consider 'code') is tested. My motivation is that that changing a JPQL statement with a mocked out EntityManager would lead to successful test execution of the code unit.
I'm using Guice and Jukito to run other (non-jpa) tests.
Does anyone have an example for this? I've tried looking around and I've yet to find a good example or framework project to handle this.
Arquillian persistence? DBUnit?
Related
I recently setup a new project that is using Spring-Data-Couchbase and I am completely stumped on how I should approach unit and integration testing here.
Typically with JPA I can mock out my Repository somehow (assuming this is similar for couchbase with Spring) and this is okay for unit testing, but normally for JPA I wire up an in memory database and have a full integration testing suite. Is there any way to do this with couchbase?
Also if you don't mind mentioning any tips here as this is my first major NoSQL project :) Thanks!
Couchbase does not run in-memory unfortunately. For unit testing you would have to mock Couchbase's API. There is a CouchbaseMock project to facilitate that: https://github.com/couchbase/CouchbaseMock
There is also the possibility to use a runner prior to launching your test. There is probably a maven plugin that would allow you to run Couchbase or a Couchbase Docker image.
I (after a while without touching JPA) started a project with Hibernate 4.1, JPA2 and Spring. It is a maven project with a common life cycle.
Upon running mvn test I get the expected result of not finding the required database objects (connection is successful as expected). All my researches and experiments, however, proved not enough to make something that seemed to be a common situation.
I expect to be able to have maven drop/create the schema the local development database while executing unit tests; I imagined that hibernate3-maven-plugin (version 3.0 ideally) should handle this but I didn't manage to have it working. I don't expect any automatic insertion of data (for this I could use DBUnit or even better have each test generate its own test data, but this plays no role here) but I do expect that the schema be refreshed on the test database, reflecting the current state of my annotated model classes. I suppose this would be bound to process-test-resources phase.
I expect to generate a (or set of) sql file with the (current) schema definition, but the best result I got reflects the issue described here: Maven + Spring + Hibernate: hibernate3-maven-plugin hbm2ddl fails for reason "Caused by: java.lang.NullPointerException" (no solution so far).
Am I missing something silly or is it really not possibile at this time?
I would be very happy if someone could provide me any of
proper documentation of how this is supposed to be achieved
an working example using hibernate 4
any guidelines of practical ways of achieve my goals with some other strategy.
If it's of any relevance, database is Postgres 9.1.
Thanks in advance.
One way of doing it is to use Arquillian. You can create a separate deployment package for each test or for a suite of tests, with it's own persistence.xml and datasources. Use the hbm2dll setting in the persistence.xml to either create-drop or update the schema:
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
If you want to prepopulate the database, you can either add a import.sql to your deployment which will be executed by hibernate on application startup, or use the Arquillian Persistence extension.
Here is a complete arquillian test setup as example:
#RunWith(Arquillian.class)
public class MyTest {
#Deployment
public static Archive<?> createTestArchive() {
return ShrinkWrap.create(WebArchive.class, "myTest.war")
.addPackages(true, "com.example")
.addAsResource("testSeeds/seed.sql", "import.sql")
.addAsResource("in-mem-persistence.xml", "META-INF/persistence.xml")
.addAsWebInfResource("in-mem-datasource.xml");
}
One downside is that the in-container tests will be slower than simple unit tests.
I am not sure how well Arquillian is able to play nice with Spring, I have only used it for Java EE applications, so please tell if it is of any help.
Again an answer to my own question.
To achieve the result I wanted I had to chain in maven the execution of hibernate3-maven-plugin's hbm2ddl on process-classes phase with another execution of sql-maven-plugin on the process-test-resources phase. The first generates the sql for Hibernate's model and the second applies it to the database.
With hindsight, seems actually a decent and clean solution.
I'm still interested in knowing the best practices, if they differ from my solution, to achieve the goal of setting up the database for testing with maven from a Hibernate model.
I'm currently figuring out how to make my Wicket Application testable.
Basically, it is a Wicket / Hibernate / Apache Derby setup. Hibernate is used as a filter (as seen on: http://community.jboss.org/wiki/OpenSessionInView / see HibernateSessionRequestFilter) and has a hibernate.cfg.xml file as configuration.
What I want to do is be able to use WicketTester with a custom database that I can rebuild from scratch each testrun. Ideally, a test would contain the connection parameters for Hibernate
Basically, my question is on how to dynamically or at startup-time switch my database?
And more abstract: what is a good approach for this kind of testing?
See mockito also. I used it in a lot tests - very helpful.
Example:
when(someDao.findByOwner(isA(Owner.class))).thenReturn(your-result);
See Unit Testing Hibernate with HSQLDB.
I used to use DBUnit to populate my database with classes/records expected by my Unit tests, and I noticed that they do sort of the same thing using Boostrap.groovy in Grails, but I am wondering if this is the kosher way of doing this in Grails.
Is it better just to setup DBUnit within Grails? Or does Grails have it's own way of doing this?
I wouldn't recommend Bootstrap.groovy for loading test data. It's likely to become unwieldy, particularly if you want to use different datasets for different tests. There are a number of DBUnit Grails plugins that you could use to simplify integrating DBUnit into a Grails app (though you can also just use the JAR directly).
There are also some plugins that provide Grails-specific ways of loading test data. The Fixtures plugin seems to be one of the most popular.
I've always used a combination of Bootstrap.groovy using the environments block and the tests setUp()/tearDown() methods. Sometimes utilizing a base test class.
This is a bit of an odd question, but it has been bothering me for a few months now. I have built a JPA-based web application using Wicket + Hibernate (built with Maven), and want to test the DAO layer directly. I created a specific src/test/resources/META-INF/persistence.xml file that I used for testing, but have been running into conflicts with WTP and the like. To get around these issues, I created a separate test project where the unit tests live. Is there a better way to manage unit tests for a JPA project without having duels between persistence files?
Addendum: Would other test frameworks (TestNG, for example) make this any easier?
You may want to try mockito. The test works like this:
You use mockito to "implement" EntityManager. Instead of the real code, you use the methods of mockito to say "if the application calls getReference(), then return this object". In the background, mockito will create a proxy instance which intercepts the Java method calls and returns the values which you specify. Calls to other methods will return null.
Mocking things like createQuery() works the same way but you first need to create a mockup of Query and then use the same approach as in getReference() (return the query mockup).
Since you don't use a real EM, you don't need a real persistence.xml.
A much more simple solution would be if you could set some property to change the name of the persistence.xml file but I don't think that this is possible.
Some other links that may help:
How to configure JPA for testing in Maven
Suggest a JPA Unit test framework
We use dual persistence.xml files for production and test runtimes but it is a classpath related issue only (we use Eclipse but do not rely on WTP plugins heavily). The only difference between the two is that the production version doesn't contain entity definitions.
We don't use a mocking framework to test JPA as this wouldn't add any value to our tests. The tests do run real data access with JPA that talks to PostgreSQL database.
Our approach to tests is based on Spring test framework for persistence layer: in-transaction testing. Our application is Spring-based but this approach is equally usable for arbitrary applications that want to take advantage of Spring test classes. The essence is that each test runs within a single transaction that never commits and at the end (in tearDown) it is automatically rolled back. This solves the problem of data pollution and test dependency in very nice unobtrusive and transparent way.
The Spring test framework is flexible to allow multi-transaction testing but these are special cases that constitute not more than 10% of tests.
We still use legacy support for JUnit 3.8 but new Spring TestContext Framework for JUnit 4 looks very attractive.
For setting up in-transaction test data we use in-house utility class that constructs business entities. Since it's shared between all tests the overhead to maintain and support it is greatly outweight by the benefits of having standard and reliable way to setup test data.
Spring DI helps to make tests concise and self-descriptive but it's not a critical feature.
Using Spring and Spring's unit testing is the best way to go. With spring, you don't require two persistence.xml's as your persistence.xml has nothing in it, everything is specified by spring (all we specify in our persistence.xml is the persistence-unit name) and thus you can change database configuration etc with spring.
And as topchef pointed out, spring's transaction based unit testing is great.
As mentioned here : http://www.devx.com/java/Article/36785/1954,
you can remove the following lines from your project's .settings/org.eclipse.wst.common.component to avoid deploying test resources with the web app.
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/test/java"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/test/resources"/>
You can:
Have several persistence units
Have several persistence.xml and copy them on test, and restore them later
Setup your own properties on testing, and use mockito to return your custom entity manager factory
Use spring: https://www.baeldung.com/spring-testing-separate-data-source
The first two options are the most discussed in all suggested questions, and are by far the ones I like the least.
Solution 3. would look like this:
private EntityManager entityManager;
private static EntityManagerFactory entityManagerFactory;
#BeforeClass
public static void mainTestInitClass() {
Properties pros = new Properties();
// Override production properties
pros.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
pros.setProperty("hibernate.connection.driver_class", "org.h2.Driver");
pros.setProperty("hibernate.connection.username", "sa");
pros.setProperty("hibernate.connection.url", "jdbc:h2:mem:some_test_db;DB_CLOSE_DELAY=-1;MVCC=TRUE;DATABASE_TO_UPPER=false");
pros.setProperty("hibernate.hbm2ddl.auto", "create");
entityManagerFactory = Persistence.createEntityManagerFactory("your_unit", pros);
}
#Before
public void mainTestORMSetUp() throws Exception {
this.entityManager = entityManagerFactory.createEntityManager();
}
Now you have an entity manager available for every test. Use mockito to inject it where needed.
Solution 4: Use Spring Data+Spring Boot to setup the JPA, so you don't need the Entity Factory anymore, you simply use two different application.properties (one for main, and one for test) and then you use your defined Spring Entity Repository. Alternatively you can use different spring profiles (one for tests, other for production) which would end up allowing you to do the same. This solution is the one I use. Check the URL above for more details.