I am using Spring with DbUnit to test my DAOs. I have an TestExecutionListener to add/delete data from DB before and after each test class. Here is my abstract test class
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations={"classpath:spring/test-dao.xml"})
#TestExecutionListeners(
{ DependencyInjectionTestExecutionListener.class,CleanInsertTestExecutionListener.class}
)
#DataSetLocation("classpath:data/test-dao-dataset.xml")
public abstract class AbstractDaoTests {
I have grouped my tests into a Suite and when I execute the Suite, only the first few tests run and then tests hangs indefinitely. Not sure what would be the cause of it. I don't see any exceptions either.
Any idea or pointers on what could be causing it would be very helpful.
I am able to run the individual tests but the issue happens when I try to run them in a suite.
Also, I am using Apache Commons pool BasicDataSource to access the DB.
Thanks,
Javid
Found the issue.
I was not closing the DBUnit Connection object in my TestExecutionListeners in the beforeTestClass & afterTestClass methods.
Closing the connection fixed the issue.
Thanks,
Javid
Related
I'm making some Integration Tests for my app and I'm encountering this problem I can't see how to solve.
I'm using Spring Boot 2.4.13 + Spring Data Neo4J 6.1.9
FYI, I deleted the Application default test that comes bundled when you create a project through Spring Initializr, and under /src/test/resources I have a .yml file named application.yml
My IT class looks like this:
#SpringBootTest
public class ClientIT {
#Autowired
private ClientServiceImpl service;
#Autowired
private ClientRepository repository;
#Test
void someTest() {
//Given
//When
//Then
}
}
But when I run this test I get the following Exception:
java.lang.IllegalStateException: Failed to load ApplicationContext
And this is the cause:
Caused by: java.lang.IllegalStateException: The provided database selection provider differs from the ReactiveNeo4jClient's one.
The thing is I don't use SDN's Reactive features at all in my project. I don't even understand why Spring tries to load it. I've created an Issue under the Spring Data Neo4j GitHub repository (https://github.com/spring-projects/spring-data-neo4j/issues/2488) but they could only tell me that ReactiveNeo4jDataAutoConfiguration gets automatically included if there's a Driver or Flux class in the classpath which I don't have.
I've been debugging the Spring internals while booting up the Application after JUnit Jupiter methods to no success.
What I could see is that at some point after JUnit Jupiter tests preparation/initialization, "reactiveNeo4jTemplate" gets injected into DefaultListableBeanFactory's beanDefinitionNames variable.
I've tried many combinations of different annotations intended to be used when making Integration Tests but the one time it worked was after I explicitly excluded ReactiveNeo4jDataAutoConfiguration class through
#EnableAutoConfiguration(exclude=ReactiveNeo4jDataAutoConfiguration.class)
What I've always seen in some blogposts is that by using #SpringBootTest I shouldn't worry about this kind of problem but it looks like I need to add that annotation every time I want to make a new IT test.
My Integration Tests basically consist of bootstrapping the application + web server (tomcat) along with an embedded Neo4J instance and after that, making requests to check everything works as it should. Do I really need to worry about all of this just to make these simple tests?
Thank you
References:
How do I set up a Spring Data Neo4j integration test with JUnit 5 (in Kotlin)?
SprintBootTest - create only necessary beans
Answering my own question after finding what is causing this error:
In the linked Github Issue, one of the developers says having Flux.class in the classpath forces SDN to instantiate Neo4jReactiveDataAutoConfiguration which is what is causing the other reactive beans to instantiate.
Apparently, neo4j-harness brings io.projectreactor (where Flux.class belongs) as an indirect dependency through neo4j-fabric which is the root of our problems.
The Spring Data Neo4j will be fixing this issue in a patch later this week.
I have a cucumber test setup with spring boot. There are a large number of integration tests which take a while to run. Because they share a database, the new threaded mode in cucumber 4+ does not work (as expected).
Ideally this would work in Junit also.
For each test, I would like to create a dynamic datasource with a new database/datasource instance that the test can use independently of others, allowing it to run multithreaded (and use the 12 cores I have available).
I have tried #Scope("cucumber-glue") and #Scope("prototype") on the DataSource bean, but this results in org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'dataSource': Requested bean is currently in creation: Is there an unresolvable circular reference?.
If I use the prototype scope, the bean creation method gets called each time, but gives this error, as does the glue scope.
I have also added #DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) to classes and methods, without the scope, but this seems to do nothing.
Is there a way I can either:
1. create a new datasource for each test and have hibernate create the tables?
2. pool a set of datasources that could be used by tests?
3. Populate/reinitialize the context accordingly?
A side consequence of this is that I don't believe my context is getting recreated properly between tests for other instances of the scoping.
#Configuration
public class H2DynamicDataSource {
#Autowired
private Environment env;
#Bean
#Scope("prototype")
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.build();
}
}
Cheers
R
Hopefully you've solved this.
I just went through something similar and felt like cruising around SlackOverflow to see if anyone was doing something similar (or perhaps asking about how to do something like this) and saw this post. Figured this would be a good place to drop this information in case anyone else tries to go down this road.
I think your asking two questions:
How to get multithreading working with Cucumber and Junit Cucumber?
multithreading works great but you are constrained to a single lane
of test execution by junit if your using either the Cucumber or
SpringJUnit4ClassRunner runner junit runner classes. (I suspect this is why #CucumberOptions doesnt contain a thread arg. It's useless with the current Cucumber runner implementation.)
In order to get this working I had to write my own test runner that
would defer a the entire test execution to Cucumbers Runtime
object. I used a custom cucumber plugin to cache the results and
then relay those results back to junit when asked to 'run' the
individual tests. With Cucumber behind the wheel I was able to allow
any arbitrary number of threads for my tests.
How to ensure a new spring datasource for each test?
If you're unfamiliar with how Spring cache's contexts for tests you should have a look through the documentation here https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html#testcontext-ctx-management-caching but the tl;dr: Spring's TestContextManager(this is whats under the hood of Springs junit runner) will create and store a spring context in a map keyed by your test configuration. DirtiesContext will force the context to reload.. but otherwise two tests with the same parent class are effectively guaranteed to execute in the same test context. If your datasource is a spring datasource that is initialized during boot.. you definitely need to refresh this context between tests.
Putting those two concepts together.. Cucumber-Spring provides a way to create a new context (consistent with cucumbers new 'world' per test design) for every test but it does so by disregarding any existing spring contexts or data contained therein. This may actually be helpful to you if you can trust Cucumber-Spring to correctly stand up your datasource for you.. but in my situation we had a bunch of issues using this fake context and really needed to pull objects from the default spring context. In my case I had to incorporate Springs TestContextManager into my custom plugin AND write my own Cucumber BackendSupplierimplementation to hijack Cucumbers dependency injection mechanism (effectively replacing Cucumber-Spring)
All in all, what your trying to do is a major PITA and I hope the Cucumber folks make this easier at some point.. but what your trying to do is definitely possible. Hope you got it working!
I have a problem getting Spring Boot 2.0.5 to work nicely with Kotlintest 3.1.10.
I made a test project illustrating the problem I have.
The project is a Spring Boot 2 application
with two entities, ShoppingOrder and OrderLine (to be totally unimaginative).
There is also a test case ShoppingOrderSpec which just tests the mapping by storing and retrieving the Order.
The testcase is configured like this:
#ExtendWith(SpringExtension::class)
#Transactional
#SpringBootTest
class ShoppingOrderSpec : WordSpec() {
override fun listeners() = listOf(SpringListener)
The test case is using the SpringExtension
by Spring to hook into the JUnit 5 engine. It also uses the SpringListener and Wordspec from Kotlintest to structure the tests
and do the assertions.
The SpringListener correctly autowires the dependencies, but somehow the transaction is not being created.
Running the testcase gives the following stack-trace:
2018-10-12 10:54:14.329 INFO 59374 --- [intest-engine-0] com.example.demo.ShoppingOrderSpec : Started ShoppingOrderSpec in 4.478 seconds (JVM running for 7.421)
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.demo.ShoppingOrder.lines, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:582)
...
at com.example.demo.ShoppingOrderSpec$1$1.invoke(ShoppingOrderSpec.kt:35)
at com.example.demo.ShoppingOrderSpec$1$1.invoke(ShoppingOrderSpec.kt:19)
So, somehow the org.springframework.transaction.annotation.Transactional annotation does not seem to work,
as removing the annotation, just gives the same response.
Anyone any ideas how to get the #Transactional being applied and respected?
You can't use JUnit Jupiter extensions with KotlinTest as they are different engines. Junit Jupiter is an implementation on top of Junit Platform, like KotlinTest is, but anything written specifically for Jupiter won't work with KotlinTest. Anything written for Junit Platform should work however.
Unfortunately, the naming choices by the JUnit team are poor imo, and so people think JUnit Jupiter is the same thing as JUnit Platform.
Anyway, those
#ExtendWith(SpringExtension::class)
#Transactional
#SpringBootTest
extensions are not going to mean anything to KotlinTest, anymore than they would for Spek or whatever. ExtendWith is a Jupiter specific annotation that tells it to use the SpringExtension class. The KotlinTest equivilent is SpringListener which you've already wired in.
I'm not sure if #SpringBootTest will be picked up or not by Spring. Support may need to be added for that depending on what it does.
Finally #Transactional works by creating proxies on the methods, but since in more advanced testing frameworks like KotlinTest, the test containers are not methods, but just arbitrary functions, it won't be able to intercept.
I think in this case, you might need to create a proper method and annotate that, or try using the AnnotationSpec rather than StringSpec or whatever other spec base class you are using, which uses actual methods that you could annotate.
I have created a couple unittest classes in the same package. All these classes have exactly one testcase and have the same annotation as shown below:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes= {TestConfig.class} )
When I run these testcases, I want each testcase be run in its own application context. But it seems all the testcases in the same package share one single application context, be it run from maven command line, or in Eclipse select the package to run as junit.
If I duplicate the TestConfig wiht names like TestConfig1, TestConfig2, etc. and annotate different test class with different TestConfig class, then each test will run in its own context instance.
Is there other elegant method to achieve this?
Thanks a lot.
This is the default behavior of Spring test. Spring test default caches the application context across the tests. This decreases the test execution time.
I dont know about your use case. If u have any where u are dirtying the application context(changing the state of the beans that are managed by springs that is affecting the subsequent tests ) then u can go for annotating the test method with #DirtiesContext. Spring test reloads the context for these methods. See below link how to use DirtiesContext.
https://docs.spring.io/spring/docs/current/spring-framework-reference/html/integration-testing.html#testcontext-ctx-management-caching
Use this feature carefully whenever needed only as this may shoot up your test execution time exponentialy.
I want to start a server once before all tests and then shutdown the server after all tests have executed.
In Spring Boot 1.3, I could create a #Component with #PostConstruct to start a server once before tests were executed and then #PreDestroy to stop the server after all tests executed.
After upgrading to Spring Boot 1.5, #PostConstruct is called before every #Test method. #PreDestroy is called for every #Test but only after all tests have executed!
What changed and/or how should I be doing it now?
Similar question with answer - https://stackoverflow.com/questions/42839765/can-you-get-spring-boot-junit-tests-to-use-the-same-server
Apparently, I was being smart while upgrading and changed my WebEnvironment to use RANDOM_PORTs. This causes the Context Caching to be unique for each test class which in turn causes the #Component to be recreated each test.
Thanks