JUnit
Spring Boot
Application.java
Testing
Software Development

How to JUnit Test Spring-Boot's Application.java

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In a Spring Boot project, Application.java is the main bootstrap class and often the quickest signal that your configuration wiring is healthy. Testing it is usually less about business logic and more about confirming the application context starts with expected beans and profiles. A focused JUnit setup gives early detection of dependency or configuration regressions.

What to Test in Application.java

The main entry class typically looks simple, but startup can fail for many reasons, such as invalid configuration properties, missing beans, or conflicting auto-configuration. A practical test plan usually includes:

  1. context startup test,
  2. optional smoke checks for critical beans,
  3. optional profile-specific startup test.

A minimal boot class:

java
1package com.example.demo;
2
3import org.springframework.boot.SpringApplication;
4import org.springframework.boot.autoconfigure.SpringBootApplication;
5
6@SpringBootApplication
7public class Application {
8    public static void main(String[] args) {
9        SpringApplication.run(Application.class, args);
10    }
11}

Basic Context Load Test with JUnit 5

The most common startup test uses @SpringBootTest.

java
1package com.example.demo;
2
3import org.junit.jupiter.api.Test;
4import org.springframework.boot.test.context.SpringBootTest;
5
6@SpringBootTest
7class ApplicationContextTest {
8
9    @Test
10    void contextLoads() {
11        // Test passes if Spring context starts successfully.
12    }
13}

This simple test catches a large class of issues because Spring must build the full context.

If startup is expensive, use slices for narrower tests elsewhere and keep one full-context smoke test here.

Verify Critical Beans Explicitly

For high-value services, add assertions so test failures are easier to diagnose.

java
1package com.example.demo;
2
3import static org.assertj.core.api.Assertions.assertThat;
4
5import org.junit.jupiter.api.Test;
6import org.springframework.beans.factory.annotation.Autowired;
7import org.springframework.boot.test.context.SpringBootTest;
8import org.springframework.context.ApplicationContext;
9
10@SpringBootTest
11class ApplicationBeansTest {
12
13    @Autowired
14    private ApplicationContext context;
15
16    @Test
17    void requiredBeansExist() {
18        assertThat(context.containsBean("dataSource")).isTrue();
19        assertThat(context.getBeanNamesForType(MyService.class)).isNotEmpty();
20    }
21}

This helps when multiple configuration classes interact and startup errors are not obvious.

Test Profile-Specific Startup

Many projects use different profile configs for local, test, and prod. Validate that intended profile boots cleanly.

java
1package com.example.demo;
2
3import org.junit.jupiter.api.Test;
4import org.springframework.boot.test.context.SpringBootTest;
5import org.springframework.test.context.ActiveProfiles;
6
7@SpringBootTest
8@ActiveProfiles("test")
9class ApplicationTestProfileContextTest {
10
11    @Test
12    void contextLoadsWithTestProfile() {
13    }
14}

Combine this with src/test/resources/application-test.yml to isolate test-time settings such as in-memory databases.

Reduce Startup Cost in Tests

Full context tests can be slow. You can keep reliability while reducing overhead:

  • disable nonessential integrations in test profile,
  • use embedded or containerized test database only when needed,
  • avoid loading unnecessary external clients.

Example test properties:

yaml
1spring:
2  main:
3    lazy-initialization: true
4  datasource:
5    url: jdbc:h2:mem:testdb
6    driver-class-name: org.h2.Driver

Use with caution. Lazy initialization can mask some startup errors, so keep at least one realistic startup path in CI.

Optional Test for main Method Invocation

Most teams do not need to test main directly, but you can if policy requires coverage.

java
1package com.example.demo;
2
3import org.junit.jupiter.api.Test;
4
5class ApplicationMainTest {
6
7    @Test
8    void mainRunsWithoutThrowing() {
9        Application.main(new String[]{});
10    }
11}

This gives minimal value compared with @SpringBootTest, but can satisfy strict coverage gates.

Add Web Layer Startup Verification

If your application depends on web configuration, test startup with a web environment mode to catch servlet stack issues early.

java
1@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
2class ApplicationWebStartupTest {
3
4    @Test
5    void webContextLoads() {
6    }
7}

This helps detect problems in embedded server setup, filter registration, and endpoint wiring that a non-web context may not expose.

Common Pitfalls

A common mistake is treating contextLoads as sufficient for all testing. It only confirms startup, not endpoint correctness or service behavior. Pair it with unit and integration tests.

Another issue is running full context tests with production-like external dependencies. If tests depend on unavailable services, they become flaky. Use test profiles, mocks, or dedicated test infrastructure.

Developers also over-assert bean names directly, which can break during refactoring. Prefer type-based checks when possible.

Summary

  • Test Application.java primarily as a startup and wiring smoke check.
  • Use @SpringBootTest for full context verification.
  • Add focused assertions for critical beans and profile-specific startup.
  • Keep startup tests fast and deterministic with test configuration.
  • Combine startup tests with unit and integration layers for full coverage.

Course illustration
Course illustration

All Rights Reserved.