Issue
I have 16 Unit test case files. Each in this format:
@SpringBootTest
class UserServiceTest {
@Autowired
UserService userService;
@MockBean
SomeDependency someDependency;
@Test
...and so on
}
Whenever I run mvn clean install
, it seems that spring is restarting/loading context 16 times. I see these logs 16 times:
[INFO] Running com.base.UserServiceTest
2021-07-16 04:35:39.421 [INFO ] [main] o.s.t.c.s.AbstractTestContextBootstrapper - Neither @ContextConfiguration nor @ContextHierarchy found for test class [com.base.UserServiceTest], using SpringBootContextLoader
2021-07-16 04:35:39.423 [INFO ] [main] o.s.t.c.s.AbstractContextLoader - Could not detect default resource locations for test class [com.base.UserServiceTest]: no resource found for suffixes {-context.xml, Context.groovy}.
2021-07-16 04:35:39.424 [INFO ] [main] o.s.t.c.s.AnnotationConfigContextLoaderUtils - Could not detect default configuration classes for test class [com.base.UserServiceTest]: UserServiceTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration.
2021-07-16 04:35:39.473 [INFO ] [main] o.s.b.t.c.SpringBootTestContextBootstrapper - Found @SpringBootConfiguration com.base.Application for test class com.base.UserServiceTest
2021-07-16 04:35:39.475 [INFO ] [main] o.s.t.c.s.AbstractTestContextBootstrapper - Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener, org.springframework.boot.test.autoconfigure.webservices.client.MockWebServiceServerTestExecutionListener, org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.event.ApplicationEventsTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener, org.springframework.test.context.event.EventPublishingTestExecutionListener]
2021-07-16 04:35:39.476 [INFO ] [main] o.s.t.c.s.AbstractTestContextBootstrapper - Using TestExecutionListeners: [org.springframework.test.context.web.ServletTestExecutionListener@4dc599a7, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener@635f2d9b, org.springframework.test.context.event.ApplicationEventsTestExecutionListener@7e83380f, org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener@6000fc20, org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@1e95926, org.springframework.test.context.support.DirtiesContextTestExecutionListener@1bc08f75, org.springframework.test.context.transaction.TransactionalTestExecutionListener@7ce49f42, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener@1b629d02, org.springframework.test.context.event.EventPublishingTestExecutionListener@5089c721, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener@4fad5162, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener@176bd95a, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener@186edc38, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener@6c0b0db, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener@2343c720, org.springframework.boot.test.autoconfigure.webservices.client.MockWebServiceServerTestExecutionListener@6aab6b1b]
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.5.0)
2021-07-16 04:35:39.520 [INFO ] [main] o.s.b.StartupInfoLogger - Starting UserServiceTest using Java 11.0.2 on
2021-07-16 04:35:39.523 [INFO ] [main] o.s.b.SpringApplication - The following profiles are active: local
2021-07-16 04:35:40.197 [INFO ] [main] o.s.m.w.MockServletContext - Initializing Spring TestDispatcherServlet ''
2021-07-16 04:35:40.197 [INFO ] [main] o.s.w.s.FrameworkServlet - Initializing Servlet ''
2021-07-16 04:35:40.199 [INFO ] [main] o.s.w.s.FrameworkServlet - Completed initialization in 1 ms
2021-07-16 04:35:40.211 [INFO ] [main] o.s.b.StartupInfoLogger - Started UserServiceTest in 0.732 seconds (JVM running for 9.613)
[INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.918 s - in com.base.UserServiceTest
This causes 2 problems:
- There are a lot more tests to be added. Even with 16 test files, it takes around 20 seconds to execute. So the process is slow.
- My application uses JPA to connect with DB, and during
mvn clean install
, although the application builds successfully, it gives this error in logs random number of times:
2021-07-16 04:35:52.741 [ERROR] [main] c.z.h.p.HikariPool - HikariPool-11 - Exception during pool initialization. org.postgresql.util.PSQLException: FATAL: remaining connection slots are reserved for non-replication superuser connections
I wonder if this context reloading is causing this as I perform mvn clean install
often and that there might be a connection leak somewhere.
Using JUnit 5/Jupiter and Spring 5.
Any help in fixing above 2 points is appreciated. Thanks.
Solution
Spring Test caches your TestContext and re-uses it for another test if the context configuration fits.
However, if all your tests have a different setup (e.g., the first test wants a mocked version of class A and the second test wants a mocked version of class B), caching won't help and Spring has to start a new context.
If you streamline the context setup for all your tests, Spring will reuse it and hence make the test execution fast.
In addition, the test you added (using @SpringBootTest
) is not a unit test (well - it always depends on the definition) as it starts the entire Spring context.
If your plan is to write unit tests for your business logic, rather use just JUnit 5 and Mockito. These tests are fast and there's no Spring support and hence no context started.
For a broad overview of unit, integration, and end-to-end testing strategies for Spring Boot applications, take a look at this article.
Answered By - rieckpil
Answer Checked By - Marie Seifert (JavaFixing Admin)