TestRestTemplate in Spring Boot: Integration Testing REST APIs the Right Way
Learn how to use TestRestTemplate in Spring Boot for robust REST API integration testing.
20+ years shipping production Java in banking & fintech. Drawn from code that ran under real load.
- ✓Java 17+ installed
- ✓Spring Boot 3.2+ project with spring-boot-starter-web and spring-boot-starter-test
- ✓Basic understanding of REST APIs and HTTP methods
• TestRestTemplate is a Spring Boot test utility for integration testing REST endpoints, with built-in authentication and error handling • Unlike RestTemplate, it auto-configures for test environments and supports relative URLs • Use @SpringBootTest(webEnvironment = RANDOM_PORT) to spin up a real server • Always assert on response headers, status codes, and body content for thorough coverage • Avoid calling external services in integration tests; mock them with WireMock or Testcontainers
Think of TestRestTemplate as a smart robot that pretends to be a web browser visiting your application. You tell it to go to a URL, and it reports back what your app sent — the status code, response body, headers. It's like having a QA engineer in your codebase that runs every time you build.
Integration testing in Spring Boot can feel like walking a tightrope. You want confidence that your REST endpoints work end-to-end, but you don't want to spin up a full infrastructure stack every time you run tests. That's where TestRestTemplate comes in. Available since Spring Boot 1.4.0, TestRestTemplate is a specialized version of RestTemplate designed specifically for integration tests. It integrates seamlessly with Spring Boot's test slice annotations, supports auto-configuration of authentication (Basic Auth, OAuth2), and handles relative URLs by resolving them against the local server's base URL. In this guide, we'll explore how to use TestRestTemplate to write meaningful integration tests for a payment-processing application. You'll learn how to test CRUD operations, error handling, and security constraints — all while avoiding the common pitfalls that lead to flaky tests or missed bugs. By the end, you'll have a battle-tested approach to REST API testing that has saved my team countless production incidents at 3 AM.
Setting Up TestRestTemplate in Spring Boot 3.2
To start using TestRestTemplate, you need a Spring Boot test class with @SpringBootTest and a web environment. The RANDOM_PORT mode boots the embedded server on a random port, avoiding port conflicts. TestRestTemplate is auto-configured by Spring Boot's test slice, so you can inject it directly. Here's how to set up a test for a payment-processing API:
What the Official Docs Won't Tell You
The official Spring Boot documentation shows you how to use TestRestTemplate, but it glosses over critical nuances. First, TestRestTemplate is not a drop-in replacement for RestTemplate in production code — it's designed for tests only. Second, it uses a special RequestFactory that doesn't follow redirects by default, which can surprise you when testing 3xx responses. Third, the default error handler throws exceptions on 4xx and 5xx responses, which is the opposite of what you want in integration tests. You should always override it with a no-op or custom handler. Finally, TestRestTemplate does not support relative URLs by default; you must use the restTemplate.getRootUri() method or prepend the base URL. Here's how to configure it properly:
Testing CRUD Operations with TestRestTemplate
CRUD testing with TestRestTemplate is straightforward. Use exchange() for full control, or convenience methods like getForEntity(), postForEntity(), put(), and delete(). Always assert on the HTTP status code, headers (like Location), and body content. For a payment API, test the happy path and edge cases like missing fields or negative amounts. Here's an example:
Testing Error Handling and Validation
A robust API must return meaningful error responses. TestRestTemplate makes it easy to verify error scenarios. Use the custom error handler from Section 2, then assert on the status code and error body. For validation errors (e.g., @Valid), Spring Boot returns 400 Bad Request with a default error structure. Test both client errors (4xx) and server errors (5xx). Here's how:
Testing Security with TestRestTemplate
If your API uses Spring Security, TestRestTemplate can automatically handle Basic Auth or bearer tokens. Use the withBasicAuth() method or configure a JWT token in the request headers. For OAuth2, you can mock the token endpoint. Test both authenticated and unauthenticated access to ensure your security configuration is correct. Here's an example:
Advanced: Testing with External Dependencies Using WireMock
Real integration tests mock external services. WireMock is a popular library that stubs HTTP endpoints. Combine it with TestRestTemplate to test your API's interaction with downstream services (e.g., payment gateways). Use @SpringBootTest with WireMock's @AutoConfigureWireMock annotation. This ensures your tests are fast and deterministic. Here's a pattern:
Common Pitfalls and How to Avoid Them
After years of writing integration tests, I've seen the same mistakes repeatedly. First, using @MockBean in integration tests breaks the point of testing real beans. Second, not resetting state between tests leads to flaky results. Third, testing only the happy path leaves error handling untested. Fourth, ignoring response headers (like rate limiting or caching) misses critical functionality. Finally, over-mocking the entire context defeats the purpose of integration testing. Always test with the real Spring context and mock only external boundaries.
Debugging TestRestTemplate Failures in CI
When TestRestTemplate tests fail in CI, you often can't see the actual HTTP response. Use logging to capture request and response details. Enable RestTemplate logging in application-test.properties: logging.level.org.springframework.web.client.RestTemplate=DEBUG. Also, print the response body in test assertions. For complex failures, use a custom TestExecutionListener that captures failures with curl commands. Here's a debug strategy:
The Case of the Silent 500 Error
TestRestTemplate.getRestTemplate().setErrorHandler(new DefaultResponseErrorHandler()) and explicitly assert on response status codes. Added a global exception handler for the missing exception type.- Always configure TestRestTemplate to not throw exceptions by setting a custom error handler
- Never assume tests cover error paths just because they pass
- Use response-based assertions (status code, body) over exception-based testing
restTemplate.withBasicAuth("testuser", "testpass").getForEntity(...)Check spring.security.user.name and password in application-test.properties| File | Command / Code | Purpose |
|---|---|---|
| PaymentControllerIntegrationTest.java | @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) | Setting Up TestRestTemplate in Spring Boot 3.2 |
| TestRestTemplateConfig.java | @TestConfiguration | What the Official Docs Won't Tell You |
| PaymentCrudTest.java | @Test | Testing CRUD Operations with TestRestTemplate |
| PaymentErrorHandlingTest.java | @Test | Testing Error Handling and Validation |
| SecurityTest.java | @Test | Testing Security with TestRestTemplate |
| PaymentWithWireMockTest.java | @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) | Advanced |
| CommonMistakesExample.java | @MockBean | Common Pitfalls and How to Avoid Them |
| DebugConfigTest.java | @Test | Debugging TestRestTemplate Failures in CI |
Key takeaways
Interview Questions on This Topic
How would you test a REST endpoint that requires a JWT token using TestRestTemplate?
Frequently Asked Questions
20+ years shipping production Java in banking & fintech. Drawn from code that ran under real load.
That's Spring Boot. Mark it forged?
3 min read · try the examples if you haven't