Test Cases: Mocking Database using Spring beans - java

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.

Related

Persistence of data in each iteration of PactVerify in the provider

What is the best way to perform a test of contracts, when the endpoint of the provider performs a persistence of data?
For example, the registration of a client. Should I consider the rollback of the data in the pipeline?
Considering that Client Driven Contract tests are not (usually) supposed to be functional tests, I mock everything bellow my provider Resource that handles the rest call. Therefore, no data is persisted and it also simplifies the test a lot, because you remove any dependencies on external components, including databases.
For instance, if your ClientResource (or ClientController, depending on your name pattern) calls a ClientRepository, the ClientRepository would be mocked.
I make the decision based the the tradeoffs of mocking/not mocking for each particular codebase. I've worked on microservices where it was very easy to just rollback the transaction, so I used the real database for those tests. I've also worked on systems where it made more sense to mock the repository, as suggested by Fabricio. I always mock downstream service dependencies.

Spring boot REST application testing approach

I have a Spring boot + REST application. When I need to write unit testing, should I directly invoke the service beans or call the rest controller? If I invoke the rest controller directly, I have to use RestTemplate and invoke the rest api as a client, right?
What would be the best and required practice?
If I invoke the service beans directly it will result in less code coverage because controller methods code will be not covered. Is that acceptable?
Hmm, this is a complex question but I'll answer as best I can. A lot of this will depend on you/your organization's risk tolerance and how much time they want to invest in tests. I believe in a lot of testing, but there is such a thing as too much.
A unit test tests the unit of code. Great, but what's a unit? This article is a pretty good discussion: http://martinfowler.com/bliki/UnitTest.html but a unit is basically the smallest testable part of your application.
Much literature (e.g. https://www.amazon.ca/Continuous-Delivery-Reliable-Deployment-Automation/dp/0321601912/ ) describes multiple phases of testing including unit tests which are very low level and mock externalities such as DBs or file systems or remote systems, and "api acceptance tests" (sometimes called integration tests although this is a vague term that can mean other things). This latter type fires up a test instance of your application, invokes APIs and asserts on responses.
The short answer is as follows: for unit tests, focus on the units (probably services or more granular), but the other set of tests you describe, wherein the test behaves like a client and invokes your api, are worthwhile too. My suggestion: do both, but don't call both unit tests.
Best Approach is to Test VIA Controllers. WebServices are entered and values are returned here. So Controller is having quite a good role in this. There can be small logic as well, you may miss that
You can Try Using the MockMvc Method for testing controllers.
Reference: Reference-1, Reference-2
Or use the RestTemplate as you mentioned in question Reference-3
It is based on what you want to test, you can separate your test, specially if you have team of developers, make test case to test your business "services", and another test cases as integration test to use REST template, in this case you can figure your bugs faster and easier.
It depends on what you want to do.
One approach would be to unit test the units of work, like the service and the MVC controller. These test will only test eventual logic found in this classes and try to reach a high branch coverage, if applicable.
Besides this, you can write an integration test that makes the HTTP request, goes to the real service bean and only mock an eventual resource access.
For integration tests you can use Spring's support, see here: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/integration-testing.html#spring-mvc-test-framework

How to unit test that the application of Spring AOP advice is as expected?

We are working on a large team with many off-shore resources, most of whom are at a junior-level and we do not expect to fully understand how to use Spring AOP. Despite that, we still want to use Spring AOP because of rapidly changing (by our customer) nature of the applications cross-cutting concerns.
Our concern is ensuring that the advice is being applied how we expect it is, meaning:
ensuring that it is getting applied to the methods we want it to get applied to
that it is not getting applied to any other methods
What worries us most is that the juniors could make changes that could break our point cuts by doing things like renaming methods. Also, we are worried about which advice gets applied where because some services on exception should rollback the transaction, while some should log and carry-on, which we want to implement using AOP as well.
Therefore we want to programmatically test the application of Spring AOP advice, but we are not sure how to best proceed.
tl;dr: How to unit test the application the application of Spring AOP advice?
PS- please no semantic complaints of the use of "unit" vs "integration" test here.
The best I could come up with is a Spring unit test, and create mock implementations of all the services (targetted and not), and have them injected into the unit test, and then have the services the advice calls into mocked as well, and then call each method on each service and then verify whether or not the advice's mocked service was called. For every. single. method. on every. single. service. :-S
Hopefully, there is some higher-level facility where you could query into Spring to ask where it gets applied, but we have not uncovered any such ability in any of the tutorials so-far.

Multiple DAO's vs One DAO with configuration file

I'm currently in the process of creating a data access layer for an application. This application will initially connect to an Oracle database but will later also connect to a DB2 database.
For connecting to the database I will use JDBC. At this time I'm considering my options. As I see it I have two (primary) options.
1) Create a design with support for multiple DAO factories, each instantiating the DAO's specific to their database. Initially, this design will only have one factory. Later it will be extended with a second factory and DAO classes.
2) Create one DAO factory which instantiates multiple DAO's for the different models. This DAO factory builds the DAO's based on a configuration file, which contains the JDBC driver path and connection url.
I'm tempted to choose the second option, which seems to remove quite some code duplication in the DAO's. Could anyone give the pros and cons of both approaches?
Why would you choose for multiple DAO factories (abstract factory pattern) when you don't really need it when using JDBC?
I believe Spring or Guice would be the best and cleanest option for you, where you'd want to pick the appropriate DAO implementation and inject it in the DAO consumer layer. Spring will also enable you to use Spring-JDBC which takes care of most of the boilerplate code making your DAO Impls easy to manage and code. You can also use ORMs with Spring.
Taking into account that you can't use Spring (even though it would save you from a lot of coding), I would say that 2nd variant is more appropriate to you, because you are going to implement dependecy management yourself and 1 dependency (single DAO factory) is always easier than 2.
Though, if you expect that amount of places were DAOs for both databases are used together is not big, then separating them into 2 factories will have a better structural meaning and is more clean. But if you expect, that pretty much every class that uses DAOs will need both worlds (Oracle + DB2), then again stick to the 2nd variant.
In any case, try to consider again about dependecy injection framework usage, because that what you are going to implement yourself anyway with all your factories.

JPA-based JUnit Test Best Practices

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.

Categories

Resources