As spring beans are nothing but POJOs, we can always write unit test for individual beans that 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 Spring container.
Spring TestContext
The Spring TestContext Framework supports full integration with JUnit through a custom runner.
This example shows how to use TestContext framework with JUnit 4.
Example
Creating a simple Spring application.
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 {
}
Order
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;
}
}
OrderService
package com.logicbig.example;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class OrderService {
public String placeOrders(List<Order> orders) {
//just a dummy service
return orders.size() + " orders placed";
}
}
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;
}
}
Test class
By annotating test classes with @RunWith(SpringJUnit4ClassRunner.class) or the shorter @RunWith(SpringRunner.class) variant, we can write standard JUnit 4 unit and integration tests. That means we can have full support of spring context loading and dependency injection of the beans in our tests.
package com.logicbig.example;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = AppConfig.class)
public class ShoppingCartTest {
@Autowired
private ShoppingCart shoppingCart;
@Test
public void testCheckout() {
shoppingCart.addItem("Item1", 3);
shoppingCart.addItem("item2", 5);
String result = shoppingCart.checkout();
Assert.assertEquals("2 orders placed", result);
}
}
mvn test OutputD:\example-projects\spring-core-testing\spring-testing-getting-started>mvn test [INFO] Scanning for projects... [INFO] [INFO] --------< com.logicbig.example:spring-testing-getting-started >--------- [INFO] Building spring-testing-getting-started 1.0-SNAPSHOT [INFO] from pom.xml [INFO] --------------------------------[ jar ]--------------------------------- [INFO] [INFO] --- resources:3.3.1:resources (default-resources) @ spring-testing-getting-started --- [INFO] skip non existing resourceDirectory D:\example-projects\spring-core-testing\spring-testing-getting-started\src\main\resources [INFO] [INFO] --- compiler:3.3:compile (default-compile) @ spring-testing-getting-started --- [INFO] Nothing to compile - all classes are up to date [INFO] [INFO] --- resources:3.3.1:testResources (default-testResources) @ spring-testing-getting-started --- [INFO] skip non existing resourceDirectory D:\example-projects\spring-core-testing\spring-testing-getting-started\src\test\resources [INFO] [INFO] --- compiler:3.3:testCompile (default-testCompile) @ spring-testing-getting-started --- [INFO] Nothing to compile - all classes are up to date [INFO] [INFO] --- surefire:3.2.5:test (default-test) @ spring-testing-getting-started --- [INFO] Using auto detected provider org.apache.maven.surefire.junit4.JUnit4Provider [INFO] [INFO] ------------------------------------------------------- [INFO] T E S T S [INFO] ------------------------------------------------------- [INFO] Running com.logicbig.example.ShoppingCartTest [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.565 s -- in com.logicbig.example.ShoppingCartTest [INFO] [INFO] Results: [INFO] [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 [INFO] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 3.574 s [INFO] Finished at: 2025-11-13T20:58:46+08:00 [INFO] ------------------------------------------------------------------------
What is @ContextConfiguration?
This class-level annotation is used to specify what application configuration to load for Spring context. In above example, we specified 'classes' element with the value of our JavaConfig class
What is @RunWith annotation?
If a JUnit class or its parent class is annotated with @RunWith, JUnit framework invokes the specified class as a test runner instead of running the default runner. See the tutorial on @RunWith
SpringJUnit4ClassRunner vs SpringRunner
Both runners are exactly the same . SpringRunner was introduce just as a short name.
SpringRunner is a subclass of SpringJUnit4ClassRunner and it does nothing special but just provide a short name to be used with @RunWith.
public final class SpringRunner extends SpringJUnit4ClassRunner {
public SpringRunner(Class<?> clazz) throws InitializationError {
super(clazz);
}
}
SpringRunner was introduced in Spring 4.3.0
In this example we used SpringRunner. Checkout this example of SpringJUnit4ClassRunner.
Example ProjectDependencies and Technologies Used: - spring-context 6.2.13 (Spring Context)
Version Compatibility: 3.2.9.RELEASE - 6.2.13 Version compatibilities of spring-context with this example: Versions in green have been tested.
- spring-test 6.2.13 (Spring TestContext Framework)
- junit 4.13.2 (JUnit is a unit testing framework for Java, created by Erich Gamma and Kent Beck)
- JDK 25
- Maven 3.9.11
|