Rollback changes in test after manual interaction with the datasource? - java

I'm using dbsetup for my db tests. The problem is I can't manage to get data rolled back after each test using the aproach which have always worked which is annotating the test case (or method) with #Transactional annotation. I suppose this happens because dbsetup uses the DataSource itself so Spring can't get track of what's being done to the database. How to make this work?

DbSetup is not tight to Spring in any way. It gets a JDBC connection from a DataSource and commits it when it's done.
The recommended way of using DbSetup is to clear and populate the tables before each test. Using a DbSetupTracker allows avoiding useless repopulations in case a test uses the same data as a previous test, and this previous test hasn't altered the data. This is described in the user guide.

Related

Is there some way to rollback redis data after finish java test code?

Is there some way to rollback the data in redis after test code run.
I worked on a java web project using spring boot 2.
I know redis does not provided rollback operation.
So using another redis (like some embedded redis) in test can ensure test code does not change the redis data. And make a mocked redis client to get data in test redis first and if no data then get from the origin Redis.
Does it workable?
And is there a ready made package implements this function?
Or has any simpler way to rollback?
First of all, you should be clear on terms. Either you are doing a real (narrow) unit test, then you absolutely decouple your code under test from any "real" resource, such as databases or file systems or remote servers. In other words: then you mock out such dependencies.
Otherwise, you are doing functional testing. And there are simply too many options to give a meaningful answer here. One example would be Redis Mock.
But as said: the real answer is that you get clear on your requirements. You should do unit-tests that mock out on a lower level, directly at the (single) class under test.

DAO layer testing strategy with JUnit and Spring

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.

Debugging JUnit Tests in a Hibernate driven Spring Application

Maybe this has been answered already, but i did not find any suggestions out there...
My Project is a Spring Utility Project, the database i use is MySQL and for persistence i´m using Hibernate in combination with c3p0 connection pooling. i´m on spring 3.2 and hibernate 3.5.
So here is what i want to do:
I want to debug a JUnit test, step over some persistence functions (save, update, etc. ) and then check the entries manually in the database via SQL. Because of the JUnit tests always running in a transaction, i cannot check the entries in the database, because a rollback happens every time a test finished / a commit never occurs.
Is there a way to fake transaction existence, or bypassing them during JUnit tests?
Perhaps you can flush the transaction in Hibernate during your debugging session and force Spring/Hibernate to write to the database.
Or you can turn off transactions for your debugging session.
Rather than fake transaction existence, the best approach to looking at the database while the transaction is taking place is to query with an isolation level that allows dirty reads. The mechanism for doing this varies from database to database, and in MySQL you can use
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
prior to querying.
Clearly you will also need to force Hibernate to flush writes to the database during your test, and set your breakpoint after the flush.

rollback nested transaction in java

We run junit tests to test our java codebase. Each test will read/write some data to a mysql database(possibly multiple tables). It seems that the tests are leaving behind data that is interfering with tests that run after it. Is it possible that we can abort/rollback all changes done by the test at the end of each unit test?
We are using cactus framework to test ejbs in glassfish application server. The ejbs can call code in the AS that can read/write to the DB.
We are using hibernate and jdbc to talk to the DB.
A possible solution would be resetting the database after each test with a simple database script you could run after each test, but this would consume a LOT of time.
If you are running integration tests, then you will be using real EJBs, there is not much you can do about this because it would be complicated to make them understand when the test begins and ends. For a simple operation you could force an Exception to cause a rollback, but if you use more than 1 transaction in a single test this won't work.

Feasible database testing

I've been assigned with the task to investigate how we should perform our testing in an upcomming project.
Im currently trying to decide whenever or not we should have structured tests for our SQL statements. I've come to the conclusion that it might be a good idea to have test suits for the "get" statements to make sure that they return the correct data but not to test insert, delete or update since this can easily be verified with a select in the DB and foregin key exceptions will be thrown if some depedency is missing.
Now, i've been checking out DBunit to be used to perform these tests but I have a couple of conserns:
1.Is it feasible to perform tests as described above? Or is the time put to create these tests and insert test data not worth the effort? Pherhaps it's enough to let the developers test this ad-hoc?
2.It seems as it might be time consuming to decide on proper test data for each test. Test data should manually be inserted in the flat-xml-file that DBunit requires (if you let the expected data be generated by DBunit you are dependant on the SQL that fetches that data). Is this the case?
3.Is there a better, simpler way to perform database tests to verify SQL statements?
The project will be using Hibernate, Java and a MS SQL Server
you can use dbunit or you can build the db content programatically (in each test). the important part is to let the testing framework (e.g. spring test) do the rollback after each test. once you setup the environment it's easy to test the DML done in a single transaction (get, insert, delete).
if you want to test DDL (some databases does that outside of a transaction) then you have to do manual rolling back or creating a database from scratch before each test (e.g. in memory db). DDL testing is usually not needed as hibernate does the validation part
and yes: you should test your queries - it's worth it to spend some time on preparing environment

Categories

Resources