09 - Spring Testing Notes
A beginner-to-advanced guide to Spring testing, JUnit 5, Mockito,
@SpringBootTest,@WebMvcTest,@DataJpaTest, MockMvc, and Testcontainers for Spring Professional Certification candidates. Covers Spring Framework 6 and Spring Boot 3 concepts.
Table of Contents
- Why Testing Matters in Spring
- JUnit 5
- Mockito
@SpringBootTest@WebMvcTest@DataJpaTest- MockMvc
- Testcontainers
- Choosing the Right Spring Test Annotation
- Common Test Dependencies
- Interview Questions
- Cheat Sheet
- Key Takeaways
1. Why Testing Matters in Spring
Testing in Spring applications usually happens at multiple levels:
| Level | Purpose | Common Tools |
|---|---|---|
| Unit test | Test one class in isolation | JUnit 5, Mockito |
| Slice test | Test one layer of the application | @WebMvcTest, @DataJpaTest |
| Integration test | Test multiple Spring components together | @SpringBootTest, Testcontainers |
| End-to-end style test | Test application behavior through HTTP or APIs | MockMvc, TestRestTemplate, WebTestClient |
The goal is not to load the whole Spring context for every test. Use the smallest test scope that proves the behavior.
2. JUnit 5
JUnit 5 is the default testing framework used by modern Spring Boot projects.
JUnit 5 has three main parts:
| Component | Purpose |
|---|---|
| JUnit Platform | Launches testing frameworks on the JVM |
| JUnit Jupiter | Programming model and annotations for JUnit 5 |
| JUnit Vintage | Runs older JUnit 3 and JUnit 4 tests |
Common JUnit 5 Annotations
| Annotation | Purpose |
|---|---|
@Test | Marks a test method |
@BeforeEach | Runs before each test method |
@AfterEach | Runs after each test method |
@BeforeAll | Runs once before all tests |
@AfterAll | Runs once after all tests |
@DisplayName | Gives a readable test name |
@Disabled | Skips a test |
@Nested | Groups related tests |
@ParameterizedTest | Runs the same test with multiple inputs |
@ValueSource | Supplies simple values to a parameterized test |
@CsvSource | Supplies comma-separated arguments |
@MethodSource | Supplies arguments from a method |
Basic JUnit 5 Test
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
class CalculatorTest {
@Test
void shouldAddTwoNumbers() {
Calculator calculator = new Calculator();
int result = calculator.add(2, 3);
assertEquals(5, result);
}
}
Assertion Examples
assertEquals(expected, actual);
assertNotEquals(expected, actual);
assertTrue(condition);
assertFalse(condition);
assertNull(value);
assertNotNull(value);
assertThrows(IllegalArgumentException.class, () -> service.process(null));
assertAll(
() -> assertEquals("John", user.getFirstName()),
() -> assertEquals("Doe", user.getLastName())
);
Parameterized Test
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import static org.junit.jupiter.api.Assertions.assertEquals;
class DiscountServiceTest {
@ParameterizedTest
@CsvSource({
"100, 10, 90",
"200, 25, 150",
"50, 0, 50"
})
void shouldApplyDiscount(int price, int discountPercent, int expected) {
DiscountService service = new DiscountService();
int actual = service.applyDiscount(price, discountPercent);
assertEquals(expected, actual);
}
}
JUnit 5 Best Practices
- Test method names should describe expected behavior.
- Prefer one behavioral reason for failure per test.
- Use
assertThrowsfor exception scenarios. - Avoid testing private methods directly.
- Keep unit tests independent from Spring when Spring is not required.
- Use parameterized tests when the same logic must be validated with multiple inputs.
3. Mockito
Mockito is used to create test doubles for dependencies. It is useful when testing a class in isolation.
Common Mockito Concepts
| Concept | Meaning |
|---|---|
| Mock | Fake object with programmable behavior |
| Stub | Predefined behavior for a mock |
| Verify | Check whether a method was called |
| Spy | Partial mock around a real object |
| Argument matcher | Flexible way to match method arguments |
Mockito with JUnit 5
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class OrderServiceTest {
@Mock
private OrderRepository orderRepository;
@InjectMocks
private OrderService orderService;
@Test
void shouldReturnOrderTotal() {
when(orderRepository.findTotalByOrderId(1L)).thenReturn(500);
int total = orderService.getOrderTotal(1L);
assertEquals(500, total);
verify(orderRepository).findTotalByOrderId(1L);
}
}
Common Mockito Methods
when(repository.findById(1L)).thenReturn(Optional.of(entity));
when(service.process()).thenThrow(new RuntimeException("failed"));
verify(repository).save(entity);
verify(repository, times(1)).save(entity);
verify(repository, never()).delete(entity);
verifyNoMoreInteractions(repository);
any();
anyString();
anyLong();
eq("ACTIVE");
@Mock vs @MockBean
| Annotation | Used In | Purpose |
|---|---|---|
@Mock | Plain unit tests | Creates a Mockito mock outside the Spring context |
@MockBean | Spring Boot tests | Adds or replaces a bean in the Spring application context |
Mockito Best Practices
- Use Mockito for dependencies, not for the class under test.
- Avoid mocking value objects, DTOs, entities, and simple data structures.
- Prefer verifying important side effects, not every internal method call.
- Do not overuse spies; they often indicate poor test design.
- Keep stubbing minimal and relevant to the test scenario.
4. @SpringBootTest
@SpringBootTest loads the full Spring application context. It is used for integration tests where multiple layers must work together.
When to Use @SpringBootTest
Use it when testing:
- Application startup and configuration.
- Service integration with repositories.
- Multiple beans working together.
- Real Spring configuration, filters, aspects, events, or transactions.
- Integration with external infrastructure through Testcontainers.
Avoid it for simple unit tests because it is slower than focused tests.
Basic Example
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import static org.junit.jupiter.api.Assertions.assertNotNull;
@SpringBootTest
class ApplicationContextTest {
@Autowired
private OrderService orderService;
@Test
void contextLoads() {
assertNotNull(orderService);
}
}
Web Environment Options
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
| Option | Meaning |
|---|---|
MOCK | Creates a mock servlet environment; does not start a real server |
RANDOM_PORT | Starts the embedded server on a random port |
DEFINED_PORT | Starts the embedded server on the configured port |
NONE | Loads application context without web environment |
@SpringBootTest with MockMvc
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest
@AutoConfigureMockMvc
class OrderIntegrationTest {
@Autowired
private MockMvc mockMvc;
@Test
void shouldGetOrders() throws Exception {
mockMvc.perform(get("/orders"))
.andExpect(status().isOk());
}
}
5. @WebMvcTest
@WebMvcTest is a Spring MVC slice test. It loads only web-layer components, not the full application context.
It usually loads:
- Controllers.
- Controller advice.
- JSON serialization components.
- Spring MVC infrastructure.
- Filters, depending on configuration.
It does not load:
- Service beans.
- Repository beans.
- Full application configuration.
Basic @WebMvcTest
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.MockMvc;
import java.util.List;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@WebMvcTest(OrderController.class)
class OrderControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private OrderService orderService;
@Test
void shouldReturnOrders() throws Exception {
when(orderService.findAll()).thenReturn(List.of(new OrderDto(1L, "NEW")));
mockMvc.perform(get("/orders"))
.andExpect(status().isOk())
.andExpect(jsonPath("$[0].id").value(1))
.andExpect(jsonPath("$[0].status").value("NEW"));
}
}
When to Use @WebMvcTest
Use it to test:
- Request mappings.
- HTTP status codes.
- Request validation.
- JSON request and response structure.
- Controller exception handling.
- Security behavior at the MVC layer.
Common Issue
If the controller depends on a service, provide it using @MockBean.
@MockBean
private UserService userService;
Without this, the test may fail because @WebMvcTest does not load service-layer beans.
6. @DataJpaTest
@DataJpaTest is a persistence slice test. It focuses on JPA repositories and entity mapping.
It usually configures:
- JPA repositories.
- EntityManager.
- Hibernate.
- DataSource.
- Transaction rollback after each test.
By default, Spring Boot often replaces the real database with an embedded database if one is available.
Basic @DataJpaTest
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
@DataJpaTest
class OrderRepositoryTest {
@Autowired
private OrderRepository orderRepository;
@Test
void shouldFindOrderByStatus() {
Order order = new Order();
order.setStatus("NEW");
orderRepository.save(order);
Optional<Order> result = orderRepository.findFirstByStatus("NEW");
assertTrue(result.isPresent());
assertEquals("NEW", result.get().getStatus());
}
}
Using TestEntityManager
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
import static org.junit.jupiter.api.Assertions.assertEquals;
@DataJpaTest
class CustomerRepositoryTest {
@Autowired
private TestEntityManager entityManager;
@Autowired
private CustomerRepository customerRepository;
@Test
void shouldFindByEmail() {
Customer customer = new Customer();
customer.setEmail("a@example.com");
entityManager.persistAndFlush(customer);
Customer result = customerRepository.findByEmail("a@example.com").orElseThrow();
assertEquals("a@example.com", result.getEmail());
}
}
Using Real Database with @DataJpaTest
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class OrderRepositoryRealDatabaseTest {
}
@DataJpaTest Best Practices
- Use it for repository methods, JPQL queries, native queries, and entity mappings.
- Verify database constraints where relevant.
- Prefer Testcontainers when database-specific behavior matters.
- Remember that tests are transactional and usually roll back after each test.
7. MockMvc
MockMvc tests Spring MVC applications without starting a real HTTP server.
It can be used with:
@WebMvcTest@SpringBootTestplus@AutoConfigureMockMvc- Standalone controller setup
Common MockMvc Request Methods
mockMvc.perform(get("/api/users"));
mockMvc.perform(post("/api/users"));
mockMvc.perform(put("/api/users/1"));
mockMvc.perform(patch("/api/users/1"));
mockMvc.perform(delete("/api/users/1"));
POST JSON Example
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@WebMvcTest(UserController.class)
class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
void shouldCreateUser() throws Exception {
String request = """
{
"name": "John",
"email": "john@example.com"
}
""";
mockMvc.perform(post("/users")
.contentType(MediaType.APPLICATION_JSON)
.content(request))
.andExpect(status().isCreated())
.andExpect(header().exists("Location"));
}
}
Common MockMvc Result Matchers
andExpect(status().isOk());
andExpect(status().isCreated());
andExpect(status().isBadRequest());
andExpect(status().isNotFound());
andExpect(content().contentType(MediaType.APPLICATION_JSON));
andExpect(jsonPath("$.id").value(1));
andExpect(jsonPath("$.name").value("John"));
andExpect(header().string("Location", "/users/1"));
Testing Validation Errors
mockMvc.perform(post("/users")
.contentType(MediaType.APPLICATION_JSON)
.content("""
{
"name": "",
"email": "invalid"
}
"""))
.andExpect(status().isBadRequest())
.andExpect(jsonPath("$.errors").exists());
MockMvc Best Practices
- Use
@WebMvcTestfor fast controller tests. - Use
@SpringBootTestwith@AutoConfigureMockMvcwhen filters, security, or full wiring matters. - Assert status, content type, headers, and important response fields.
- Avoid asserting the entire JSON response unless the full contract matters.
8. Testcontainers
Testcontainers provides lightweight, disposable Docker containers for integration tests.
It is commonly used for:
- PostgreSQL.
- MySQL.
- MongoDB.
- Kafka.
- Redis.
- RabbitMQ.
- LocalStack.
Why Use Testcontainers
Embedded databases are fast, but they may not behave exactly like production databases. Testcontainers helps test against real infrastructure.
Example: PostgreSQL-specific SQL, JSONB columns, database indexes, case sensitivity, extensions, and transaction behavior are better tested with real PostgreSQL than with H2.
Basic PostgreSQL Testcontainer
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import static org.junit.jupiter.api.Assertions.assertTrue;
@Testcontainers
@SpringBootTest
class OrderServiceIntegrationTest {
@Container
@ServiceConnection
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:16-alpine");
@Test
void shouldUsePostgresContainer() {
assertTrue(postgres.isRunning());
}
}
Dynamic Property Registration
For Spring Boot versions or setups where @ServiceConnection is not used:
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
@Testcontainers
class DatabaseIntegrationTest {
@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:16-alpine");
@DynamicPropertySource
static void configureProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgres::getJdbcUrl);
registry.add("spring.datasource.username", postgres::getUsername);
registry.add("spring.datasource.password", postgres::getPassword);
}
}
Testcontainers with @DataJpaTest
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
@Testcontainers
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class OrderRepositoryPostgresTest {
@Container
@ServiceConnection
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:16-alpine");
}
Testcontainers Best Practices
- Use Testcontainers when production-like infrastructure behavior matters.
- Keep containers static when possible to avoid restarting them for every test method.
- Prefer lightweight images such as Alpine variants when appropriate.
- Avoid using Testcontainers for every unit test; reserve it for integration tests.
- Ensure Docker is available in the test environment.
9. Choosing the Right Spring Test Annotation
| Requirement | Recommended Approach |
|---|---|
| Test one class with mocked dependencies | JUnit 5 plus Mockito |
| Test controller request and response behavior | @WebMvcTest plus MockMvc |
| Test repository query or entity mapping | @DataJpaTest |
| Test several Spring beans together | @SpringBootTest |
| Test MVC behavior with full application wiring | @SpringBootTest plus @AutoConfigureMockMvc |
| Test real database behavior | Testcontainers plus @DataJpaTest or @SpringBootTest |
| Test external service integration | Testcontainers, WireMock, or mocked client depending on scope |
10. Common Test Dependencies
Maven
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>postgresql</artifactId>
<scope>test</scope>
</dependency>
Gradle
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.testcontainers:junit-jupiter'
testImplementation 'org.testcontainers:postgresql'
11. Interview Questions
Basic Questions
- What is the difference between unit testing and integration testing?
- What are the main components of JUnit 5?
- What is the purpose of
@Testin JUnit 5? - What is the difference between
@BeforeEachand@BeforeAll? - What is the use of
assertThrows? - Why should unit tests be independent and repeatable?
- What is Mockito used for?
- What is the difference between a mock and a spy?
- What is the difference between stubbing and verification in Mockito?
- What is the difference between
@Mockand@InjectMocks?
Spring Boot Testing Questions
- What does
@SpringBootTestdo? - Why is
@SpringBootTestslower than slice tests? - What are the different
webEnvironmentoptions in@SpringBootTest? - What is the purpose of
@AutoConfigureMockMvc? - What is
@WebMvcTestused for? - Which beans are loaded by
@WebMvcTest? - Why do we often use
@MockBeanwith@WebMvcTest? - What is
@DataJpaTestused for? - Does
@DataJpaTestload service beans? - Why does
@DataJpaTestusually roll back transactions after each test?
MockMvc Questions
- What is MockMvc?
- Does MockMvc start a real HTTP server?
- How do you test a POST request with JSON using MockMvc?
- How do you verify HTTP status and response body using MockMvc?
- When should you use MockMvc with
@WebMvcTest? - When should you use MockMvc with
@SpringBootTest? - How do you test validation errors using MockMvc?
- How do you test controller advice with MockMvc?
Testcontainers Questions
- What problem does Testcontainers solve?
- Why might H2 be insufficient for repository integration tests?
- How does Testcontainers help with production-like testing?
- What is the purpose of
@Testcontainers? - What is the purpose of
@Container? - What is
@DynamicPropertySourceused for? - What is
@ServiceConnectionin Spring Boot tests? - How can Testcontainers be used with
@DataJpaTest? - What are the trade-offs of using Testcontainers?
- Why should containers often be declared as static fields?
Scenario-Based Questions
- You need to test a service method that depends on a repository. Which tools would you use?
- You need to test only controller validation and JSON response structure. Which annotation is best?
- You need to test a custom Spring Data JPA query. Which annotation is best?
- You need to test that the full application context starts successfully. Which annotation is best?
- You need to test PostgreSQL-specific behavior. Which tool should you use?
- A
@WebMvcTestfails because a service bean is missing. How do you fix it? - A repository test passes on H2 but fails on PostgreSQL. What should you change?
- A test using
@SpringBootTestis slow. How can you improve it? - You need to verify that a dependency method was called once. How do you do that in Mockito?
- You need to verify that invalid input causes an exception. Which JUnit assertion should you use?
12. Cheat Sheet
JUnit 5
| Need | Use |
|---|---|
| Mark test method | @Test |
| Run setup before each test | @BeforeEach |
| Run setup once before all tests | @BeforeAll |
| Check equality | assertEquals(expected, actual) |
| Check exception | assertThrows(Exception.class, executable) |
| Group assertions | assertAll(...) |
| Run same test with multiple values | @ParameterizedTest |
Mockito
| Need | Use |
|---|---|
| Create mock | @Mock |
| Inject mocks into tested class | @InjectMocks |
| Enable Mockito in JUnit 5 | @ExtendWith(MockitoExtension.class) |
| Stub method | when(mock.method()).thenReturn(value) |
| Verify method call | verify(mock).method() |
| Verify call count | verify(mock, times(1)).method() |
| Match any string | anyString() |
| Match exact value with matchers | eq(value) |
Spring Boot Test Annotations
| Annotation | Scope | Typical Use |
|---|---|---|
@SpringBootTest | Full application context | Integration tests |
@WebMvcTest | MVC slice | Controller tests |
@DataJpaTest | JPA slice | Repository tests |
@AutoConfigureMockMvc | Adds MockMvc | MVC testing with full context |
@MockBean | Spring context mock | Replace a bean in Spring tests |
@AutoConfigureTestDatabase | Test database config | Control embedded database replacement |
MockMvc
| Need | Use |
|---|---|
| GET request | mockMvc.perform(get("/path")) |
| POST JSON | mockMvc.perform(post("/path").contentType(APPLICATION_JSON).content(json)) |
| Check status | .andExpect(status().isOk()) |
| Check JSON field | .andExpect(jsonPath("$.field").value(value)) |
| Check header | .andExpect(header().string("Name", "value")) |
| Check content type | .andExpect(content().contentType(APPLICATION_JSON)) |
Testcontainers
| Need | Use |
|---|---|
| Enable Testcontainers extension | @Testcontainers |
| Declare container | @Container |
| PostgreSQL container | PostgreSQLContainer<?> |
| Register Spring properties manually | @DynamicPropertySource |
| Auto-connect container in Spring Boot | @ServiceConnection |
| Prevent test DB replacement | @AutoConfigureTestDatabase(replace = NONE) |
Quick Decision Guide
| If You Need To Test | Use |
|---|---|
| Pure business logic | JUnit 5 |
| Business logic with mocked dependency | JUnit 5 plus Mockito |
| Controller mapping and validation | @WebMvcTest plus MockMvc |
| Repository query | @DataJpaTest |
| Repository query against real database | @DataJpaTest plus Testcontainers |
| Full application wiring | @SpringBootTest |
| Full MVC request flow without real server | @SpringBootTest plus @AutoConfigureMockMvc |
| Production-like external infrastructure | Testcontainers |
13. Key Takeaways
- Prefer fast unit tests for business logic.
- Use Mockito to isolate a class from its dependencies.
- Use Spring slice tests when only one layer needs to be tested.
- Use
@SpringBootTestonly when full application wiring is required. - Use MockMvc for testing Spring MVC request and response behavior.
- Use Testcontainers when real infrastructure behavior matters.
- Choose the smallest test scope that gives confidence.