I'm trying to unit (integration) test a method annotated with Spring's #Async.
The test sets up some data in in-memory h2 database, then runs the asynchronous method. Asynchronous code does not see test data :O
Removing #Async fixes the problem.
Any help? :)
I had the same error. The solution was quite simple for me: I did not put a COMMIT; to the end of my data_init-h2.sql
I presume you did not put this either. If you think about it this is quite logical. Your main thread fires up a transaction but does not actually commit it to h2. Spring fires up another thread and the #Async method is run there in a separate transaction.
Because of the lack of commit you do not see the data changes on this other thread. On the main thread you can see your data changes even before they are committed as you are in that transaction.
The transaction isn't propagated like it was before your #Async.
#Async and #Transactional: not working
Your test could commit the data and delete it either side of the test, removing Spring's automated rollback inside test #Transactionals.
You could create a default-access method that the async method calls into, that your test could also call direct, though you would no longer be testing the Async behaviour.
There's likely a nicer spring implementation that supports what you need, making the transaction available but I don't have it.
Related
I've been working with Spring and Hibernate for about two years. Recently I have also been working on testing. Now I'm not quite sure if I understood everything correctly. Do I understand correctly that the following methods exist? **If I make wrong assumptions, please correct me!
Method 1:
Situation: The test class is annotated with #Transactional. The test data is created manually in an #BeforeEach method and stored in a repository.
Advantages: Through #Transactional annotation, all (BeforeEach, Test-Method, AfterEach) methods are executed in one transaction, which can be undone directly by rollback and therefore no emptying of the database is necessary.
Disadvantages: Since everything is carried out in one transaction and canceled directly by rollback, the data never ends up correctly in the database? Perhaps errors would occur during a commit? This means that the test does not reflect a real situation.
Method 2:
Situation: The test class has no #Transactional annotation. The test data is created and stored in an #BeforeEach method.
Advantages: Since the #Transactional annotation is missing, all calls of the service or controller are executed in a separate transaction, reflecting a real situation.
Disadvantages: Since everything is executed in separate transactions, the database must be completely emptied manually after each test (disable constraints and empty each table).
I have another question, but it's more subjective Do you like the initialization of test data using the #BeforeEach method and manual creation of objects and saving via repository or SQL scripts in #Sql annotation better? Initializing via SQL scripts feels faster in my opinion.
I am trying to figure out why #Transactional does not rollback data in envers audit table after each test and how to fix it.
How can I make that happen in spring integration tests?
I have tried with #DirtiesContext and that makes it work but it's rather workaround and makes tests run much longer which I don't like.
Does any of you have any idea how to make it work?
Hibernate Envers acts as a transaction-commit-time audit solution. What that ultimately means is that all the persistence changes that happen during a transaction are examined and a set of work unit operations are cached in memory. In short, the only time Envers flushes operations to the audit schema is immediately before the commit of a successful transaction.
So how does this all work from a Hibernate point of view?
Hibernate Envers registers 2 very critical callback operations with Hibernate ORM when a transaction that operates on an audited entity is detected, a before and after transaction completion callback. The before callback is what actually performs the flushing of the audit changes to the audit tables and the after is responsible for cleaning up any resource allocations that are related to the transaction.
The only time that the before callback actually happens is when the hibernate transaction coordinator is asked to commit the transaction. If the transaction has been marked for rollback when the commit is requested, then the before callback is skipped.
The after callback always happens no matter the transaction status.
It would seem whats likely happening is #Transactional is creating the transaction boundary and the method is then invoked to perform its operations and when the method exits, the annotation forces a transaction commit leading to the observed behavior.
I can see a few options for you:
Override transaction behavior for tests to be read-only.
Design tests to clean-up their test data after validating the test use case.
Design tests to work even if existing test data exists in the tables.
Disable Envers via configuration if it isn't needed as a part of that integration test.
I want to make a database call before every method within my Spring application annotated with #Transactional started executing transaction.
There are few requirements for this:
This database call has to be part of the actual transaction that is about to begin.
The database connection used for the Transaction has to be same to be used for this database call and should setup some database data before 'real' transaction begins.
Is there something that Spring supports to achieve this goal ? One way I am thinking is to write own Aspect cloning more or less all Transactional code as is. Other way is to write Aspect. Not sure if there are more ways.
I have the following problem trying to integrate Hystrix into an existent Spring Boot application. I am using boot with spring data (jpa repositories). The structure of the app is pretty simple,
we have Resources -> Services -> Repositories.
I enabled Hystrix support and annotated one of the service methods that returns an entity as follow:
#HystrixCommand(fallback="getDealsFallback")
public Page<Deal> getDeals(...) {
// Get the deals from the Index Server.
return indexServerRepository.findDealsBy(...);
}
public Page<Deal> getDealsFallback(...) {
// If IndexServer is down, query the DB.
return dealsRepository.findDealsBy(...);
}
So this works as expected, the real problem resides actually when I return the Entity to the client. I am using OpenEntityManagerInViewFilter so I can serialize my model with its relations.
When I use #HystrixCommand in my service method, I get a LazyInitializatioException when It tries to serialize.
I know the cause (or at least I suspect what is the problem), and is because Hystrix is executing in another thread
so is not part of the transaction. Changing the Hystrix isolation strategy from THREAD to SEMAPHORE, works correctly since its the same thread, but I understand that is not the correct way to approach the problem.
So my question is, How can I make the Hystrix executing thread be part of the transaction. Is there any workaround that I can apply?
Thanks!
It is a little old thread, but maybe someone meets this problems too. There is an issue in github about this.
The reason is, hystrix will run in separate thread, which is different from where the previous transaction is. So the transaction and serialization for lazy will not work.
And the 'THREAD' is the recommended execution strategy too. So if you want to use both hystrix and transaction, you should use them in 2 level calls. Like, in first level service function, use transaction, and in second level service function, use hystrix and call first level transactional function.
Is it possible to register some kind of callback with a JTA transaction in a Spring application?
I've got some mock services that are standing in for remote services that belong to another application that's normally accessed using Spring's HttpInvoker. These mock services model data in-memory in a trivial fashion using Maps and the like.
The Unit tests don't necessarily know which of these services might get used; the service the test case is targetting might use them behind the scenes.
The unit tests are transactional, and Spring's SpringJUnit4ClassRunner will rollback the transaction after each test, meaning that the state fo our unit test database is preserved between tests.
How can I rollback the state of this custom in-memory service implementation? If there was a way of finding out if there's a transaction currently going on, then I was hoping there'd be a way of registering a callback with the TransactionManager to be executed before the transaction is completed.
I don't think it's a good idea to clean up test mock in such an implicit way - tests usually perform cleanup explicitly.
However, if you really want, take a look at TransactionSynchronizationManager.registerSynchronization().