Topic revision clinic · Testing · 13 misses · 35 drills

Testing — the most volatile section you own

Testing has scored 100% → 100% → 33% → 60% → 75% across your last five papers. That is not a knowledge problem, it is a coverage problem: you know the headline annotations and guess at the edges. These thirteen show exactly where the edges are — and four of them are one table: which of the four configuration annotations adds to the context and which one silently replaces it.

4
Config discovery (a third)
4
Under-selection
2
"NOT true" polarity slips
0
Invented names — a first
Where the thirteen fall.
Test configuration & discovery 4@TestConfiguration ×2 · bootstrapper · TestContext Slice tests (@WebMvcTest) 3what it loads ×1 · asked "NOT" ×2 Context & infrastructure 3servlet mocks · Flyway · starter-test Profiles & properties 2@ActiveProfiles · precedence Mocking 1@Mock vs @MockBean

One genuinely good sign. This bank was full of invented names — @TestContext and MockBeanAutoconfiguration were both offered, and both were correctly rejected. Fabricated names peaked at eleven on attempt #10 and are now zero here. That failure mode is fixed. What is left is the opposite problem: ticking too few boxes (4 of 13) and reading past the word "NOT" (2 of 13).

Master table 1 — the four configuration annotations: which ADD and which REPLACE

Four of the thirteen are this table. It is the single highest-value thing on this page.

AnnotationModuleComponent-scanned?Effect on a Boot test context
nested @Configuration
(a static inner class in the test)
spring-contextyes — found as the primary configREPLACES the application's configuration. Auto-configuration and component scanning disappear.
@TestConfigurationspring-boot-testno — meta-annotated @TestComponent, excluded from the primary searchADDS beans on top of the discovered configuration.
@SpringBootConfigurationspring-boot—The marker the bootstrapper searches upward for. Meta-present on @SpringBootApplication.
@ContextConfigurationspring-test—Plain Spring TestContext wiring. Not needed in a Boot test — @SpringBootTest does discovery itself.

One sentence and you have the table: the annotation with "Test" in the name is the additive one; the plain one is the destructive one. Your instinct was the exact reverse, on two separate questions.

@SpringBootTest with no classes = ... — how the context is found:

  test class package                    com.example.service
        │  SpringBootTestContextBootstrapper
        │  → SpringBootConfigurationFinder walks UP
        ▼
  com.example.service   → nothing
  com.example           → @SpringBootApplication  ✔  ← used as the ROOT config
                            (meta-annotated @SpringBootConfiguration)

  then, and only then:
    nested @TestConfiguration in the test  →  MERGED in as extra beans
    nested plain @Configuration in the test →  used INSTEAD, walk never happens

Two failure messages worth memorising: a test in a package above the app class gives Unable to find a @SpringBootConfiguration; two candidate classes on the classpath give Found multiple @SpringBootConfiguration annotated classes. Both are fixed with @SpringBootTest(classes = Application.class).

Master table 2 — the three test annotations, side by side

Three of the thirteen are @WebMvcTest. Every one of them is answered by a single column here.

@SpringBootTest@WebMvcTest@DataJpaTest
Context loadedthe whole thingweb layer onlyJPA layer only
MockMvconly with @AutoConfigureMockMvcauto-configuredno
TestRestTemplateyes — with RANDOM_PORT / DEFINED_PORTNOno
Real HTTP serveronly RANDOM_PORT / DEFINED_PORTnevernever
@Service / @ComponentloadedNOT loaded — @MockBean themnot loaded
@Repositoryloadednot loadedloaded
Flyway / Liquibaserunsn/aruns
Speedslowestfastfast

What @WebMvcTest auto-configures — the list the exam draws from: MockMvc · @Controller · @ControllerAdvice · @JsonComponent · Converter / GenericConverter · Filter · WebMvcConfigurer · HandlerMethodArgumentResolver · Spring Security when it is on the classpath. It is also meta-annotated @ExtendWith(SpringExtension.class). The only thing on that list you will be offered as a false option is TestRestTemplate, because it needs a real port.

Master table 3 — property precedence, lowest to highest

Q42 asked which wins. You picked OS environment variables, which is the right answer to the runtime version of the question — but this stem was about tests.

  lowest
    1  SpringApplication.setDefaultProperties(...)
    2  application.properties / application.yml
    3  application-{profile}.properties          ← profile-specific
    4  OS environment variables                  ← your answer
    5  command-line arguments                    ← the winner at RUNTIME
    6  @TestPropertySource                       ← the winner IN A TEST
    7  TestPropertyValues set programmatically
  highest

Two answers, one ladder. "Highest precedence" in a running application = command-line arguments. "Highest precedence" in a test = @TestPropertySource. Read the stem for the word test before you answer.

Master table 4 — @Mock vs @MockBean

One miss, but this pair is asked in nearly every paper.

AnnotationComes fromWhat it doesWhat makes it work
@MockMockitoCreates a mock and assigns it to the field. Not in the Spring context.@ExtendWith(MockitoExtension.class) (JUnit 5) · @RunWith(MockitoJUnitRunner.class) (JUnit 4) · or MockitoAnnotations.openMocks(this)
@MockBeanSpring Boot TestReplaces the bean of that type in the ApplicationContext.Any Spring Boot test annotation — the MockitoPostProcessor is registered automatically
@SpyMockitoWraps a real instance with spy semanticssame as @Mock
@SpyBeanSpring Boot TestWraps an existing context bean with spy semanticssame as @MockBean

JUnit knows nothing about @Mock. It is a Mockito annotation; something has to scan for it. That is the whole of Q18. And @Mock inside a @SpringBootTest does not reach the context — only @MockBean does. Bonus fact: every distinct @MockBean configuration creates a fresh context, which is why over-using it makes a suite crawl.

The pattern that cost you two of these thirteen — and eleven across the series

Q25 asked which statement is NOT true. Q46 asked which is not correct. On both you selected a statement that was true — which is to say, you answered the question that was not being asked. This is now the tenth and eleventh polarity slip across your papers and clinics, and it is worth more marks than any single topic on this page.

The mechanical fix, and it costs eight seconds: when the stem contains NOT, except, false or incorrect, write T or F beside every option first, then pick the F. Do not try to hold the inversion in your head while you read — that is exactly when it flips back.

And note Q46's answer: "None of the above." All three listed statements about @WebMvcTest were true, so the option that is not correct was the catch-all. "None of the above" on a NOT-question means every listed statement is true. Do not dismiss it as filler.

Four of thirteen were under-selection — your largest single error mode

On Q2, Q24, Q34 and Q48 every box you ticked was right. You simply stopped ticking too early. Q48 in particular had all four options correct — the eighth "everything is true" question in this series.

The fix is the same one that took MVC from 50% to 100%: rule each option true or false on its own merits, then tick every true one. Do not ask "which is the best answer" on a multi-select — there is no best, only true and false. If a stem says "select one or more", the expected count is frequently three or four, not two.

Jump to a section

① Test configuration & discovery — 4 ② Slice tests — 3 ③ Context & infrastructure — 3 ④ Profiles & properties — 2 ⑤ Mocking — 1 ⑥ 35 drills

① Test configuration & discovery 4 misses

A third of the bank, and all four are master table 1.

Q1 · nested @TestConfiguration vs nested @Configuration

@TestConfiguration adds. A plain nested @Configuration replaces.

Your answer: "Nested @TestConfiguration replaces the primary configuration; nested @Configuration is an addition." That is the correct statement read backwards. The word "Test" marks the safe, additive one.

@TestConfiguration is meta-annotated with @TestComponent, which excludes it from the bootstrapper's search for a primary configuration — so the app's real config is still found, and the test class's beans are merged on top. A plain nested @Configuration is a valid primary candidate, so the search stops there and your application configuration never loads.

@SpringBootTest
class MyTest {
    @TestConfiguration          // additive — app config still loads
    static class Extra {
        @Bean Clock testClock() { return Clock.fixed(Instant.EPOCH, ZoneOffset.UTC); }
    }
}
Hook: "Test" = addition. Plain = replacement. To override an existing bean rather than add one, you also need spring.main.allow-bean-definition-overriding=true (Boot 2.1+).
Q7 · how to annotate config classes in src/test/java same fact as Q1

@TestConfiguration — because it is not picked up by component scanning

Your answer: @Configuration. It works, but it is picked up by component scanning, so it leaks into every test that scans that package. That is the exact reason @TestConfiguration exists.

Two questions, one fact, missed both times in opposite directions — Q1 you said @TestConfiguration replaces, Q7 you reached for @Configuration instead of it.

Component-scannedIntended for
@Configurationyes — picked up automaticallymain application config
@TestConfigurationno — nested, or @Imported explicitlytest-only beans
Hook: a top-level @TestConfiguration class must be brought in with @Import(MyTestConfig.class). A nested one is picked up automatically by the test that owns it.
Q35 · what must you do to configure the context in a Boot test?

Nothing — Boot walks up the package tree and finds @SpringBootConfiguration itself

Your answer: "use @TestConfiguration to point at packages to scan". @TestConfiguration registers extra beans; it declares no scan packages and does no discovery.

If the @SpringBootApplication class sits in the root package and the tests mirror that package structure, discovery is automatic. SpringBootTestContextBootstrapper runs SpringBootConfigurationFinder, which searches upward from the test's package for the first @SpringBootConfiguration, and uses its @ComponentScan and @EnableAutoConfiguration exactly as in production.

ScenarioWhat you do
Standard app, tests under the same root packageNothing
More than one candidate main class@SpringBootTest(classes = Application.class)
Narrow the context to one layera slice — @WebMvcTest, @DataJpaTest
Add a few extra beansnested @TestConfiguration
Fully custom, non-Boot config@ContextConfiguration(classes = ...) + @ExtendWith(SpringExtension.class)
Hook: adding @ComponentScan to a Boot test is not just unnecessary, it is harmful — it duplicates scanning and can register beans twice.
Q33 · statements about integration tests with Spring support wrong pick + missed the right one

Contexts are cached, not rebuilt per test class

Your answer: "A new Spring context is created for each test class." The opposite: the TestContext Framework caches one ApplicationContext per unique configuration and reuses it across every test that asks for the same one. That caching is the single biggest reason Spring test suites are tolerable. The correct statement — "context configuration can be inherited from the superclass" — you left unticked.

The four TestContext facts this question rotates through:

Hook: anything that says Spring builds a fresh context per test or per class is false. Anything that says configuration is inherited or optional is true.

② Slice tests — @WebMvcTest 3 misses

The same annotation three times, and two of them were only wrong because of the word "NOT".

Q2 · what does @WebMvcTest auto-configure? under-selection

MockMvc, @ControllerAdvice, WebMvcConfigurer — not TestRestTemplate

Your answer: every tick correct, but you stopped short of all three. You correctly rejected TestRestTemplate — that part was right.

TestRestTemplate makes real HTTP calls, so it needs a real server. Only @SpringBootTest(webEnvironment = RANDOM_PORT) (or DEFINED_PORT) starts one. @WebMvcTest never starts a server — it dispatches through MockMvc instead.

Hook: MockMvc = no server. TestRestTemplate = real server. If a stem mentions a port, it cannot be a slice test.
Q25 · which statement is NOT true? polarity

The false statement was "Spring Boot does not support @WebMvcTest"

Your answer: "Spring provides support for integration testing with the Spring TestContext Framework." That is true — so it cannot be the answer to a "which is NOT true" question.

All four options were about things Spring genuinely does: Mockito integrates via @Mock and @MockBean; the TestContext Framework is real; it supports JUnit 4 (@RunWith(SpringRunner.class)), JUnit 5 (@ExtendWith(SpringExtension.class)) and TestNG. The single planted falsehood was a denial of @WebMvcTest.

Hook: on a NOT-question, the answer is usually the option that denies a feature that exists. Scan for the negative wording — "does not support", "cannot", "is not possible".
Q46 · which statement about @WebMvcTest is not correct? polarity

All three listed statements were true, so the answer was "None of the above"

Your answer: "@WebMvcTest is meta-annotated with @ExtendWith(SpringExtension.class)." True — that is precisely how a slice test hooks into JUnit 5.

The three true statements were: it auto-configures Spring MVC infrastructure; it is meta-annotated with @ExtendWith(SpringExtension.class); it auto-configures MockMvc. With nothing false among them, the catch-all becomes the answer.

Hook: "None of the above" is a real answer, not filler. On a NOT-question it means every listed statement is true — the mirror image of the "all four options are correct" questions that have caught you eight times.

③ Context & infrastructure 3 misses

Q26 · the main advantage of Spring when writing unit tests

The mock servlet classes — MockHttpServletRequest and friends

Your answer: "All of the above." The tempting default, but the stem says unit tests. Reusing configuration files and dependency injection both require loading a container — which by definition makes it an integration test.

spring-test ships mock implementations of the Servlet API in org.springframework.mock.web, so you can exercise controllers and filters with no container at all:

Mock classSimulates
MockHttpServletRequestthe HTTP request
MockHttpServletResponsethe HTTP response
MockHttpSessionthe HTTP session
MockServletContextthe servlet context
Hook: unit test = no container. Any option that requires the Spring context to load is describing an integration test and is wrong under a "unit test" stem. And "All of the above" is only right when you have verified every option individually.
Q34 · Flyway migrations in an integration test under-selection

Five of the six statements were true — only "@SpringBootTest disables Flyway" was false

Your answer: every tick correct, but well short of five.

Flyway is auto-configured whenever it is on the classpath, and its migrations run as the ApplicationContext starts — before any test method executes.

AspectBehaviour
When migrations runautomatically, on ApplicationContext startup
Naming conventionV{version}__{description}.sql — two underscores
Which databasewhatever the active profile configures (typically H2 in application-test.properties)
A broken scriptthe context fails to load, so the test fails before it runs
@SpringBootTestdoes not disable Flyway — you must set spring.flyway.enabled=false yourself
@DataJpaTestalso runs Flyway/Liquibase, with a lighter context
Hook: V1__Create_customer_table.sql — V, version, double underscore, description. A single underscore is not recognised.
Q48 · what does spring-boot-starter-test pull in? all four correct

Every option was right — JUnit, Spring Test + Boot Test, AssertJ, Hamcrest

Your answer: fewer than four ticks on a question where nothing was false. The eighth "everything is true" question in this series.

The full contents of the starter, which is worth knowing as a list because the exam samples from it:

Hook: if a question lists testing libraries and asks which the starter brings in, the safe default is all of them. There is no common testing library it deliberately excludes.

④ Profiles & properties 2 misses

Q24 · combining multiple profiles with @ActiveProfiles under-selection

Three statements were true; the two false ones you correctly rejected

Your answer: correct ticks, too few of them. You rightly rejected "only two profiles at a time" and "Spring logs a warning on conflicts" — both invented behaviours.

With @ActiveProfiles({"test", "integration"}):

What happensDetail
Property filesapplication-test.properties and application-integration.properties are both loaded and merged
Conflicting keythe later-listed profile wins — here, integration
@Profile beansbeans for both profiles are created
How many profilesany number — there is no limit of two
Conflict warningnone — Spring resolves silently by precedence
Hook: later profile wins. For an override you actually control, use @TestPropertySource(properties = "key=value") — it outranks every profile file.
Q42 · which configuration source has the highest precedence?

In a test, @TestPropertySource — above environment variables and command-line arguments

Your answer: OS environment variables. High, but not the highest — and the option list included @TestPropertySource, which sits above both environment variables and command-line arguments within a test context.

See master table 3 for the full ladder. The distinction the exam is testing: command-line arguments win at runtime; @TestPropertySource wins in a test.

@SpringBootTest
@TestPropertySource(properties = "my.custom.value=test123")
class MyTest {
    @Value("${my.custom.value}") String value;   // "test123" — beats everything else
}
Hook: the more specific and the more local the source, the higher it ranks. A test annotation is the most local thing there is.

⑤ Mocking 1 miss

Q18 · what do you have to do for @Mock to work?

MockitoExtension (JUnit 5) or MockitoJUnitRunner (JUnit 4) — or call openMocks(this)

Your answer: "Nothing, @Mock is supported by default by JUnit." @Mock is a Mockito annotation. JUnit has never heard of it — something has to scan the fields and call MockitoAnnotations.openMocks(this).

See master table 4 for the full @Mock/@MockBean split. The three ways to activate @Mock:

@ExtendWith(MockitoExtension.class)          // JUnit 5 — preferred
@RunWith(MockitoJUnitRunner.class)           // JUnit 4
MockitoAnnotations.openMocks(this);          // manual, in @BeforeEach

The manual route works but loses strict stubbing — the runner and the extension both fail the test on unused stubs, which the manual call does not.

Hook: you also correctly rejected the invented MockBeanAutoconfiguration here. Fabricated names are no longer catching you — that was the single biggest error mode two papers ago.

⑥ Drill it — 35 questions options shuffle every reload

Reading this page will not move the score; retrieving from it will. Run the thirty-five below, then come back tomorrow and run them again.

Configuration & discovery

Slice tests

Mocking

Profiles & properties

Infrastructure

The 13 facts, one line each

Drill these — don't read them
How to use this page (1) Master table 1 first — four of the thirteen. Cover the right-hand column and answer one question: which annotation adds and which replaces. Five minutes, and a third of the bank closes. (2) Then the two behavioural fixes, which are worth more than any table here. On a NOT-question, mark every option T or F before choosing — that is two marks in this bank alone and eleven across the series. On a multi-select, rule each option true or false independently and tick all the true ones — that is four more here. (3) Master table 2 answers three questions with one column. The @WebMvcTest row is the one the exam samples from repeatedly. (4) Drill, don't re-read. Testing is the fifth clinic. Its 100% → 33% swing is a coverage problem, and coverage only comes from rotating all five clinics — 20 minutes before your next attempt beats reading one new page.
I'm your teacher — ask me anything. Say "drill the test config annotations" for master table 1 alone, "drill the slices" for @SpringBootTest vs @WebMvcTest vs @DataJpaTest, or "drill all five clinics" for the full rotation. Spring Core is now the only section without a clinic — point me at a Core bank whenever you like.
← Dashboard Mixed practice Security clinic Boot clinic Data clinic MVC clinics