Close

Spring Core Testing - Spring Core Testing Quick Concepts And Example

[Last Updated: Feb 2, 2026]

Unit testing vs integration testing

As Spring beans are nothing but POJOs, we can always write unit tests for individual beans that are simply instantiated using the new operator, without Spring or any other container. But that's not good enough if we also would like to test whether beans are wired together properly or not and whether everything works as expected when tested in a Spring container; for those scenarios, we need integration testing.

Spring TestContext

The Spring TestContext Framework is a foundational component of the Spring Framework’s spring-test module and serves as the underlying infrastructure for Spring-based testing. It provides a generic, annotation-driven programming model for both unit and integration tests. The framework manages the loading and caching of the Spring ApplicationContext, injects dependencies into test instances, and provides built-in support for transactional test execution. These capabilities are offered in a testing-framework-agnostic manner, allowing integration with frameworks such as JUnit or TestNG.

Spring integration test with JUnit 5 (JUnit Jupiter)

The Spring TestContext Framework is activated through the use of test configuration annotations such as @ExtendWith and @ContextConfiguration. The JUnit's @ExtendWith annotation (tutorials here) integrates the Spring testing support with JUnit Jupiter, while @ContextConfiguration defines how the Spring ApplicationContext should be loaded for the test. Together, these annotations bootstrap the TestContext infrastructure and enable dependency injection, context management, and other testing features.

@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = AppConfig.class)
class MyServiceTest {

    @Autowired
    private MyService myService;

}

The @Autowired annotation is available in this test because the TestContext Framework performs dependency injection on the test instance after the ApplicationContext has been created. Once the context is loaded, Spring manages the test class in a similar manner to a regular Spring-managed bean, allowing dependencies to be injected directly into fields, constructors, or setter methods.

Example

Creating a simple Spring test application.

pom.xml

<dependency>
   <groupId>org.junit.jupiter</groupId>
   <artifactId>junit-jupiter-engine</artifactId>
   <version>6.0.2</version>
</dependency>
<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-context</artifactId>
   <version>7.0.3</version>
</dependency>
<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-test</artifactId>
   <version>7.0.3</version>
</dependency>

ShoppingCart

package com.logicbig.example;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class ShoppingCart {
    @Autowired
    private OrderService orderService;
    private List<Order> orders = new ArrayList<>();

    public void addItem(String name, int qty) {
        orders.add(new Order(name, qty));
    }

    public String checkout() {
        String msg = orderService.placeOrders(orders);
        orders.clear();
        return msg;
    }

    public OrderService getOrderService() {
        return orderService;
    }
}

OrderService

package com.logicbig.example;

import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class OrderService {

    public String placeOrders(List<Order> orders) {
        //simulating order placement
        return orders.size() + " orders placed";
    }
}
package com.logicbig.example;

public class Order {
    private String item;
    private int qty;

    public Order(String item, int qty) {
        this.item = item;
        this.qty = qty;
    }

    public String getItem() {
        return item;
    }

    public int getQty() {
        return qty;
    }
}

AppConfig

package com.logicbig.example;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.logicbig.example")
public class AppConfig {
}

JUnit 5 test

In JUnit 5 we use @ExtendWith (tutorial here) rather than @RunWith
The difference between the two is, @RunWith (JUnit 4) replaces the default test runner with a custom test runner. @ExtendWith (JUnit 5) is more flexible and plugs into the extension points.

Spring provides SpringExtension to be used with @ExtendWith.
SpringExtension is actually the JUnit 5 successor to SpringRunner, both are essentially the same thing, i.e. both provides Spring context support in JUnit tests. Alternatively, you can use @SpringJUnitConfig which combines @ExtendWith(SpringExtension.class) and @ContextConfiguration.

package com.logicbig.example;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import static org.junit.jupiter.api.Assertions.assertNotNull;

@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = AppConfig.class)
public class ShoppingCartTest {

    @Autowired
    private ShoppingCart shoppingCart;

    @Test
    public void testDiCorrectness(){
        //Testing dependency injection correctness
        assertNotNull(shoppingCart);
        assertNotNull(shoppingCart.getOrderService());
    }

    @Test
    public void testCheckout() {
        shoppingCart.addItem("Item1", 2);
        shoppingCart.addItem("item2", 5);
        String result = shoppingCart.checkout();
        Assertions.assertEquals("2 orders placed", result);
    }
}

Output

$ mvn test
[INFO] Scanning for projects...
[INFO]
[INFO] ------------< com.logicbig.example:spring-testing-junit-5 >-------------
[INFO] Building spring-testing-junit-5 1.0-SNAPSHOT
[INFO] from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- resources:3.3.1:resources (default-resources) @ spring-testing-junit-5 ---
[INFO] skip non existing resourceDirectory D:\example-projects\spring-core-testing\spring-testing-junit-5\src\main\resources
[INFO]
[INFO] --- compiler:3.14.1:compile (default-compile) @ spring-testing-junit-5 ---
[INFO] Recompiling the module because of changed source code.
[INFO] Compiling 4 source files with javac [debug target 25] to target\classes
[INFO]
[INFO] --- resources:3.3.1:testResources (default-testResources) @ spring-testing-junit-5 ---
[INFO] skip non existing resourceDirectory D:\example-projects\spring-core-testing\spring-testing-junit-5\src\test\resources
[INFO]
[INFO] --- compiler:3.14.1:testCompile (default-testCompile) @ spring-testing-junit-5 ---
[INFO] Recompiling the module because of changed dependency.
[INFO] Compiling 1 source file with javac [debug target 25] to target\test-classes
[INFO]
[INFO] --- surefire:3.2.5:test (default-test) @ spring-testing-junit-5 ---
[INFO] Using auto detected provider org.apache.maven.surefire.junitplatform.JUnitPlatformProvider
[WARNING] file.encoding cannot be set as system property, use <argLine>-Dfile.encoding=...</argLine> instead
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.logicbig.example.ShoppingCartTest
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.242 s -- in com.logicbig.example.ShoppingCartTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.110 s
[INFO] Finished at: 2026-01-30T15:47:07+08:00
[INFO] ------------------------------------------------------------------------

Example Project

Dependencies and Technologies Used:

  • spring-context 7.0.3 (Spring Context)
     Version Compatibility: 5.0.0.RELEASE - 7.0.3Version List
    ×

    Version compatibilities of spring-context with this example:

    • 5.0.0.RELEASE
    • 5.0.1.RELEASE
    • 5.0.2.RELEASE
    • 5.0.3.RELEASE
    • 5.0.4.RELEASE
    • 5.0.5.RELEASE
    • 5.0.6.RELEASE
    • 5.0.7.RELEASE
    • 5.0.8.RELEASE
    • 5.0.9.RELEASE
    • 5.0.10.RELEASE
    • 5.0.11.RELEASE
    • 5.0.12.RELEASE
    • 5.0.13.RELEASE
    • 5.0.14.RELEASE
    • 5.0.15.RELEASE
    • 5.0.16.RELEASE
    • 5.0.17.RELEASE
    • 5.0.18.RELEASE
    • 5.0.19.RELEASE
    • 5.0.20.RELEASE
    • 5.1.0.RELEASE
    • 5.1.1.RELEASE
    • 5.1.2.RELEASE
    • 5.1.3.RELEASE
    • 5.1.4.RELEASE
    • 5.1.5.RELEASE
    • 5.1.6.RELEASE
    • 5.1.7.RELEASE
    • 5.1.8.RELEASE
    • 5.1.9.RELEASE
    • 5.1.10.RELEASE
    • 5.1.11.RELEASE
    • 5.1.12.RELEASE
    • 5.1.13.RELEASE
    • 5.1.14.RELEASE
    • 5.1.15.RELEASE
    • 5.1.16.RELEASE
    • 5.1.17.RELEASE
    • 5.1.18.RELEASE
    • 5.1.19.RELEASE
    • 5.1.20.RELEASE
    • 5.2.0.RELEASE
    • 5.2.1.RELEASE
    • 5.2.2.RELEASE
    • 5.2.3.RELEASE
    • 5.2.4.RELEASE
    • 5.2.5.RELEASE
    • 5.2.6.RELEASE
    • 5.2.7.RELEASE
    • 5.2.8.RELEASE
    • 5.2.9.RELEASE
    • 5.2.10.RELEASE
    • 5.2.11.RELEASE
    • 5.2.12.RELEASE
    • 5.2.13.RELEASE
    • 5.2.14.RELEASE
    • 5.2.15.RELEASE
    • 5.2.16.RELEASE
    • 5.2.17.RELEASE
    • 5.2.18.RELEASE
    • 5.2.19.RELEASE
    • 5.2.20.RELEASE
    • 5.2.21.RELEASE
    • 5.2.22.RELEASE
    • 5.2.23.RELEASE
    • 5.2.24.RELEASE
    • 5.2.25.RELEASE
    • 5.3.0
    • 5.3.1
    • 5.3.2
    • 5.3.3
    • 5.3.4
    • 5.3.5
    • 5.3.6
    • 5.3.7
    • 5.3.8
    • 5.3.9
    • 5.3.10
    • 5.3.11
    • 5.3.12
    • 5.3.13
    • 5.3.14
    • 5.3.15
    • 5.3.16
    • 5.3.17
    • 5.3.18
    • 5.3.19
    • 5.3.20
    • 5.3.21
    • 5.3.22
    • 5.3.23
    • 5.3.24
    • 5.3.25
    • 5.3.26
    • 5.3.27
    • 5.3.28
    • 5.3.29
    • 5.3.30
    • 5.3.31
    • 5.3.32
    • 5.3.33
    • 5.3.34
    • 5.3.35
    • 5.3.36
    • 5.3.37
    • 5.3.38
    • 5.3.39
    • Compatible Java Version: 17+
    • 6.0.0
    • 6.0.1
    • 6.0.2
    • 6.0.3
    • 6.0.4
    • 6.0.5
    • 6.0.6
    • 6.0.7
    • 6.0.8
    • 6.0.9
    • 6.0.10
    • 6.0.11
    • 6.0.12
    • 6.0.13
    • 6.0.14
    • 6.0.15
    • 6.0.16
    • 6.0.17
    • 6.0.18
    • 6.0.19
    • 6.0.20
    • 6.0.21
    • 6.0.22
    • 6.0.23
    • 6.1.0
    • 6.1.1
    • 6.1.2
    • 6.1.3
    • 6.1.4
    • 6.1.5
    • 6.1.6
    • 6.1.7
    • 6.1.8
    • 6.1.9
    • 6.1.10
    • 6.1.11
    • 6.1.12
    • 6.1.13
    • 6.1.14
    • 6.1.15
    • 6.1.16
    • 6.1.17
    • 6.1.18
    • 6.1.19
    • 6.1.20
    • 6.1.21
    • 6.2.0
    • 6.2.1
    • 6.2.2
    • 6.2.3
    • 6.2.4
    • 6.2.5
    • 6.2.6
    • 6.2.7
    • 6.2.8
    • 6.2.9
    • 6.2.10
    • 6.2.11
    • 6.2.12
    • 6.2.13
    • 6.2.14
    • 6.2.15
    • 7.0.0
    • 7.0.1
    • 7.0.2
    • 7.0.3

    Versions in green have been tested.

  • spring-test 7.0.3 (Spring TestContext Framework)
  • junit-jupiter-engine 6.0.2 (Module "junit-jupiter-engine" of JUnit)
  • JDK 25
  • Maven 3.9.11

spring-core-testing - Integration Testing With JUnit 5 Select All Download
  • spring-testing-junit-5
    • src
      • main
        • java
          • com
            • logicbig
              • example
      • test
        • java
          • com
            • logicbig
              • example
                • ShoppingCartTest.java

    See Also

    Join