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.
Related
I'm trying to devise an optimal strategy to unit-test DAO layer of my Spring app.
Many existing approaches like in-memory DB usage, etc (posts: 12289800, 12390813, 9940010, 12801926). do not appeal to me.
So, here is a straightforward way that occurs to me:
Create Spring test-context.xml and put there all the data needed for testing all the DAO classes;
For each test class create a template method to test CRUD operations and all 'select' operations;
Before testing, insert all needed data from test-context.xml to your real DB. We may need also some dependencies (references), so insert them as well, let's say in #Before method.
After all CRUD operations, delete all dependencies (references) from DB, let's say in #After method.
If we have a lot of dependencies, this may become a terribly expensive and laborious approach. Also we have only one #Test method (template method, to ensure the order of operations: create, read... etc.) - so one test per test class.
So, I need an advice whether this strategy is viable? What similar did you do to test your DAOs?
After all, I ended up with this strategy for testing classes responsible for interacting with the database in Spring-based app. Key thoughts:
Use an in-memory DB (H2 is OK), a separate Spring profile with test data source and settings.
Database is set up at the beginning of the entire test process from the schema.sql scripts. So we need to have the sql sources to rebuild the test database. Possibly it comes from DBA or yourself if you are designing the database on your own. Tools like liquibase or flyway are if you work with the database in a large team, where everybody needs the actual state of the database by applying incremental scripts. In this way the results setup script in managed by the tool.
Obviously each test case will require its own set of data to be initialized before executing the test. We do it by making sample.sql/clear_sample.sql scripts (a pair for each test case) to insert and delete data before and after each case. For this we can use either spring's annotations: #Sql or ScriptUtils
To help designing tests we can inject EntityManager for example for retrieving inserted with the help of sql scripts.
Basic JUnit asserts are used to compare.
Thus, we have no additional software layer, like DbUnit or anything and write isolated and maintainable unit-tests.
The unavoidable downside is that when a more or less significant change comes to the DB we need to rewrite the whole test, or even several.
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 new to JPA so after searching for a while and trying I could not figure how to do the following thing.
I want to use JPA annotated classes in unit tests, production - resin app server, and in development mode for GWT (jetty).
The problem is that I could use Persistence.createEntityManagerFactory together with META-INF/persistence.xml in unit tests and it works fine. However, it does not work on resin and I get the same error in GWT development mode.
I could get it working on resin by using #Inject annotation and resin-web.xml but not sure how to use it in GWT dev mode.
I'd like to use the same code if possible for all 3 cases: unit tests, Jetty for GWT, and resin in production. I also like to let resin handle connection pooling, and avoid using Spring if possible.
Are the any tutorials that cover this particular case or any code samples? What are the best practices?
Since you're open to using Guice, Guice can piggyback off the existing #Inject annotation.
So, the idea here is to do the same thing that Resin does when it runs your code. Resin recognizes the #Inject annotation, finds the appropriate class and instantiates, than injects that value. We can get Guice to do the same thing for us for your unit test and GWT modes.
The biggest change is you'll have to make a seperate profile for your persistence.xml. Copy your existing file and change the name. For instance, if your existing PU is "myJPAUnit", in the new file, name it "myJPAUnitLocal" like this:
<persistence-unit name="myJPAUnitLocal" transaction-type="RESOURCE_LOCAL">
</persistence-unit>
The other key change is to change transaction-type to RESOURCE_LOCAL as in the above example because your transactions aren't managed by a container.
I won't cover the pre-reqs, because there are a lot of good tutorials on Google about running Junit tests and webapps with Guice, but I thought that might be a tripping point for you. The remaining steps are something like: add the Guice filter, extend the GuiceServletContextListener, add the JPA injector to that, add your listener to the web.xml.
How to initialize Guice in a webapp: http://code.google.com/p/google-guice/wiki/ServletModule
How to add a JPA injector to Guice: http://code.google.com/p/google-guice/wiki/JPA
Good luck!
We have an application built using spring/Hibernate/MySQL, now we want to test the DAO layer, but here are a few shortcomings we face.
Consider the use case of multiple objects connected to one another, eg: Book has Pages.
The Page object cannot exist without the Book as book_id is mandatory FK in Page.
For testing a Page I have to create a Book.
This simple usecase is easy to manage, but if you start building a Library, till you don't create the whole universe surrounding the Book and Page, you cannot test it!
So to test Page;
Create Library
Create Section
Create Genre
Create Author
Create Book
Create Page
Now test Page.
Is there an easy way to by pass this "universe creation" and just test the page object in isolation. I also want to be able to test HQLs related to Page. eg:
SELECT new com.test.BookPage (book.id, page.name) FROM Book book, Page page.
JUnit is supposed to run in isolation, so I have to write the code to build all the supporting objects in the test case to create the Page. Any tips on how to accelerate the process.
Edit: Spring follows the philosophy of transaction roll-back after the tests have been run, thereyby reverting all changes. Schema changes are expected as we develop further, I want to be able to test it against the production db (backup!) on a regular basis.
I just finished a project with this exact configuration. We had great success using a stand-in HSQLDB database for the unit tests and then turning off referential integrity on the schema for those tests.
Since you're using Spring, these are the steps:
Create a new context configuration file for testing. Set up hibernate to do create-drop for the schema in this configuration.
Create your junit test. Inherit from AbstractTransactionalJUnit4SpringContextTests, the greatest abstract class in the history of the universe, and annotate the class with your new #ContextConfiguration. Also use the #TransactionConfiguration annotation to run each test in a transaction with an automatic rollback.
run the command "SET REFERENTIAL_INTEGRITY FALSE;" through the inherited simpleJdbcTemplate property in your #Before method.
dedicate the rest of the #Before to simpleJdbcTemplate calls that set up the database. Note that you no longer need to specify every referenced column, just what you're testing!
Finally write your unit tests against your DAO's.
Here's a few references that will get you moving in this direction:
http://static.springsource.org/spring/docs/2.5.x/reference/testing.html
http://www.theserverside.com/news/1365222/Unit-Testing-Hibernate-With-HSQLDB
As usual with this stuff, getting the config just right is the hard part. But once it's all working, you'll be a styling unit tester!
The Unitils extensions to junit or testng have very nice support for this. They allow you to define datasets tuned for your class under test so it only needs the part of the universe your class is seeing and then it initializes the database before the tests start.
checkout : link text
We are using it and it just works fine. A lot better that the "MockRepositories" which we used before which do not test the HQL and, also important, the hibernate transaction behaviors.
Our application has a service layer and a DAO layer, written as Spring beans.
While testing the Service Layer- I do not want to depend upon a real database so I am mocking that by creating a 'Mock' Impl for the DAO layer
So when I am testing the Service layer- I chain the Service layer beans to the Mock DAO beans
And in Production- will chain the Service layer to the 'real' DAO beans
Is that a good idea ?
Any alternate suggestion on how to mock the database layer ?
Clarification:This question is about testing the Service Layer and not the DAO layer.
While testing the service layer- I assume that either the DAO layer has already been tested or doesn't need testing.
The main thing is- how do we test service layer- without being dependent upon the DAO implementation- hence I am mocking the DAO layer
This is a technique we've been using for many years now. Note that when it comes to mocking the DAO interfaces you have some choices:
Create mock instances as real Java classes
Use a dynamic mocking framework such as jMock (my preference) or EasyMock
Dynamic mocking frameworks allow you to stub out a variety of circumstances (no data, 1 row, many rows, exception throwing) without having to create complex classes to stub out the behavior you wish to test
That's a great way to use mocking to test the database. I don't think any alternative suggestion is necessary; I think you've got the right technique already!
You are definitely on the right track.
My mocking framework of choice is Mockito
As I understand the question it is explicitly dedicated to best practices regarding testing DAO layers, as mocking a database seems nnot so straightforward as mocking the DAO layer when testing services.
Personally I'd raise the question back if it's reasonable to really unit test a DAO layer in the classical unit testing meaning. If you design your DAO layer properly it does not do much more than mapping domain objects to queries.
That said I alway propose to use an embedded database like H2, HSQL or the Java 6 embedded Derby to do things like this as mocking a datasource is really much more effort than simply raising an embedded database. Spring 3 will provide a nice builder pattern to create such databases on the fly. RC1 of it will also introduce a jdbc namespace to ease setup further. See this one for details.
But even with current Spring 2.5 branch using an embedded database is just a matter of taking the databases JAR and setting up a DataSource accordingly.