0

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:

  1. 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.
  2. 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.

3
  • 1
    You're not unit but integration testing. Dependencies in unit-tests should be mocked, such as databases and stuff. Spring has even an own section in their reference documentation dealing with integration testing. If that all does not work to your satisfaction you always have the possibility to define your own JUnit suits or runners that define the required dependencies which than can be used by the respective tests. Commented Jul 15, 2021 at 23:57
  • @RomanVottner Yes, that was the issue. For unit testing @ExtendsWith is the one to use. Commented Jul 16, 2021 at 18:08
  • If you wanted to keep running in the spring context without creating a new context for each test, you could replace your MockBean by MockInBean (from github.com/antoinemeyer/mock-in-bean) Commented Dec 4, 2021 at 14:33

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Yes @SpringBootTest was the issue. I changed it with @ExtendsWith and instead of @MockBean, using @Mock. That fixed it. Thanks

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.