Testing Spring Applications practice questions

From Spring Certified Professional (Develop) (2V0-72.22) · 27 questions on this topic

Testing Spring Applications practice questions from Spring Certified Professional (Develop) (2V0-72.22). This pack has 27 questions tagged Testing Spring Applications, drawn from its timed mock exams. 8 of them are worked through in full below — the question, every option, why each is right or wrong, and the explanation.

Worked examples for Testing Spring Applications

  1. Question 1

    What does annotating a test with @DirtiesContext cause?

    1. A. The test fails immediately

      The annotation is not a failure signal; it says nothing about the test's outcome and does not cause it to fail.

    2. B. It has no effect on context caching

      The whole point of the annotation is to affect caching — it evicts the cached context, so claiming it has no effect on caching is wrong.

    3. C. Only the database is reset, the context stays cached

      This confuses a data reset with a context reset; the annotation targets the whole ApplicationContext, not just the database, and the context is discarded rather than kept cached.

    4. D. The cached ApplicationContext is closed and rebuilt, so it is not reused by later testsCorrect answer

      Correct: the annotation signals that the test mutated the context, so the framework closes and rebuilds it instead of reusing the cached instance (Spring Framework 5.3 Reference — @DirtiesContext).

    Explanation

    @DirtiesContext signals that a test has mutated the shared ApplicationContext, so the TestContext framework evicts and rebuilds it rather than serving the cached instance to later tests. This prevents cross-test contamination by ensuring subsequent tests start from a fresh context, and it operates on the entire context, not merely on database state.

  2. Question 2

    A `@SpringBootTest` integration test class needs the Spring `ApplicationContext` it loads to treat the `test` and `embedded-db` profiles as active, so that beans annotated `@Profile("embedded-db")` are registered and beans excluded by those profiles are not. Which approach expresses this declaratively on the test class itself, using the Spring TestContext Framework?

    1. A. Annotate the test class with `@ActiveProfiles({"test", "embedded-db"})`Correct answer

      Correct. `@ActiveProfiles` is the TestContext Framework annotation that declares which bean definition profiles should be active when loading the ApplicationContext for a test class; it accepts multiple profile names and is inherited by subclasses by default.

    2. B. Annotate the test class with `@Profile({"test", "embedded-db"})`

      Confuses declaring a profile with activating one. `@Profile` marks a bean definition or configuration class as *conditional on* a profile being active; placing it on a test class does not switch any profile on for the test's context.

    3. C. Annotate the test class with `@TestPropertySource(properties = "spring.profiles.include=test,embedded-db")`

      Misuses a property-source override as a profile activator and picks the wrong property. The dedicated, supported mechanism for a test class is `@ActiveProfiles`; `spring.profiles.include` is a Boot configuration property for adding profiles from configuration files, not the TestContext profile-activation API.

    4. D. Call `System.setProperty("spring.profiles.active", "test,embedded-db")` in a `@BeforeEach` method of the test class

      Assumes profiles must be set imperatively per test method. It is not declarative, it leaks global JVM state across test classes, and it runs too late in many cases — the cached ApplicationContext is loaded before per-method setup callbacks.

    Explanation

    The Spring TestContext Framework provides `@ActiveProfiles` specifically to declare which bean definition profiles should be active when loading the ApplicationContext for an integration test; it takes one or more profile names via its `value`/`profiles` attribute. Marking the test class with `@Profile` is a category error — that annotation makes a component conditional on a profile rather than activating one. Overriding a Boot property through `@TestPropertySource` targets the property environment rather than the framework's profile-activation API and names an include property that governs configuration-file merging. Setting a JVM system property inside a lifecycle callback is imperative, global, and can run after the context has already been built and cached.

  3. Question 3

    In the Spring TestContext Framework, an `ApplicationContext` loaded for an integration test is cached and reused across subsequent tests in the same test suite run. What does the framework use as the *key* for that cache?

    1. A. The fully qualified name of the test class that first triggered the context load.

      Assumes caching is per test class, which would make the cache useless — two different test classes declaring the identical configuration would each load their own context. The key is derived from the configuration, not from the test class identity, which is precisely why unrelated classes with the same configuration share one context.

    2. B. The unique combination of the configuration parameters used to load the context — such as the declared locations/classes, active profiles, context initializers, property sources, and the ContextLoader used.Correct answer

      Correct per the TestContext framework's context caching section: the key is built from the full set of configuration attributes (locations, classes, initializers, active profiles, property sources, context customizers, context loader, parent context), so any test class producing the same key reuses the cached context.

    3. C. The name of the JUnit test method being executed, so each test method gets its own cache entry.

      Confuses the context cache with per-method test instance/transaction lifecycle. Context loading is never keyed per test method; a fresh context per method would defeat the entire purpose of caching, which exists because loading a context is expensive.

    4. D. The bean definition count of the loaded context, so contexts with the same number of beans are treated as identical.

      Invents a structural heuristic based on the loaded result rather than the declared configuration. The key must be computable *before* loading — otherwise the context would have to be built to discover it was already cached — and bean counts would collide across unrelated configurations.

    Explanation

    Loading an ApplicationContext is expensive, so the TestContext framework caches each loaded context in a static cache keyed by the unique combination of configuration parameters that produced it — declared resource locations and component classes, active profiles, ApplicationContextInitializers, test property sources, context customizers, the ContextLoader, and any parent context. Any test class whose configuration yields the same key transparently reuses the cached instance, which is why caching is a property of the configuration rather than of the test class, the test method, or the shape of the resulting bean factory. Keying on the test class would prevent sharing between classes with identical configuration; keying per method would eliminate the benefit entirely; and keying on a post-load property such as bean count is impossible because the key must be known before the context is loaded.

  4. Question 4

    How do you override specific configuration properties for a single test class?

    1. A. Per-test property overrides are not supported

      Per-test property overrides are supported, so this contradicts the framework's dedicated mechanism for setting properties on a single test class.

    2. B. @ActiveProfiles is the only mechanism and sets individual properties

      @ActiveProfiles selects which bean-definition profiles are active; it switches profiles rather than setting individual property values, and it is not the only mechanism.

    3. C. Edit the main application.properties

      Editing the main properties file changes configuration for all environments, not just one test class, so it is not a per-test override.

    4. D. @TestPropertySource(properties = {"app.timeout=1"}) (or a dedicated test properties file)Correct answer

      Correct: @TestPropertySource adds an inline or file-based property source scoped to that test class with the highest precedence (Spring Framework 5.3 Reference — @TestPropertySource).

    Explanation

    @TestPropertySource contributes an inline or file-based property source that is scoped to a single test class and takes the highest precedence, letting you override specific configuration values just for that test. This targets individual properties for one class without editing shared files that affect every environment, and it is distinct from switching bean-definition profiles.

  5. Question 5

    A base integration test class `AbstractIntegrationTest` is annotated `@ActiveProfiles("integration")`. A subclass `OrderServiceIntegrationTest extends AbstractIntegrationTest` is annotated `@ActiveProfiles("stub-payments")`. Which statement correctly describes the profiles active for the subclass's ApplicationContext, and how that default behaviour can be changed?

    1. A. Only `stub-payments` is active, because a subclass declaration always replaces the superclass declaration; adding `@ActiveProfiles(inheritProfiles = true)` would merge them.

      Inverts the default. Inheritance is enabled by default (`inheritProfiles` defaults to `true`), so the subclass merges rather than replaces; setting it to `true` explicitly changes nothing.

    2. B. Both `integration` and `stub-payments` are active, because profiles are inherited by default; setting `@ActiveProfiles(value = "stub-payments", inheritProfiles = false)` on the subclass would restrict it to `stub-payments` only.Correct answer

      Correct. `@ActiveProfiles` is inherited by subclasses by default (`inheritProfiles = true`), so the subclass's profiles are merged with those declared by its superclasses; setting `inheritProfiles = false` shadows the superclass declaration.

    3. C. Only `integration` is active, because the superclass declaration wins and a subclass cannot override or extend the active profiles.

      Treats the superclass declaration as final. The framework merges the subclass's profiles with the inherited ones; a subclass can always add profiles and can shadow the superclass entirely via `inheritProfiles = false`.

    4. D. Neither is active and context loading fails, because two `@ActiveProfiles` declarations in one class hierarchy are a configuration conflict that must be resolved with `@ActiveProfiles(resolver = ...)`.

      Invents a conflict error. Declarations in a hierarchy are merged, not rejected; the `resolver` attribute exists to supply a programmatic `ActiveProfilesResolver` for dynamic profile selection, not to settle inheritance disputes.

    Explanation

    `@ActiveProfiles` supports inheritance within a test class hierarchy: its `inheritProfiles` attribute defaults to `true`, so a subclass's declared profiles are merged with those declared by its superclasses rather than replacing them. Setting `inheritProfiles = false` is the documented way to shadow the superclass declaration so only the subclass's profiles apply. The framework never treats multiple declarations in a hierarchy as an error, and the `resolver` attribute is for plugging in an `ActiveProfilesResolver` that computes profiles programmatically — a separate concern from inheritance.

  6. Question 6

    What is a convenient way to get a disposable database for repository integration tests?

    1. A. Point the test at the production database

      Testing against production is unsafe — it risks corrupting live data and is neither disposable nor isolated, which is the opposite of what a repository test needs.

    2. B. It is not possible to test against a real database

      Testing against a real database is clearly possible, including embedded engines that run genuine SQL, so this claim is simply false.

    3. C. A mocked JDBC Driver that returns canned ResultSets only

      A fully mocked driver returning canned results does not exercise real SQL or the actual persistence behavior, so it fails to validate the repository against a real database engine.

    4. D. Use an embedded database such as H2 or HSQLDB (via EmbeddedDatabaseBuilder or Boot's auto-configuration)Correct answer

      Correct: embedded in-memory databases give fast, isolated, throwaway schemas set up via EmbeddedDatabaseBuilder or auto-configured by slices like @DataJpaTest (Spring Framework 5.3 Reference — Embedded database support).

    Explanation

    An embedded in-memory database provides a fast, isolated, throwaway schema that runs real SQL for repository integration tests, and it can be created with EmbeddedDatabaseBuilder or auto-configured by test slices such as @DataJpaTest. This is safer than touching a production database and more realistic than a mocked driver that never executes actual queries.

  7. Question 7

    In a JUnit Jupiter test class that uses the default per-method lifecycle, what is required of a method annotated with @BeforeAll?

    1. A. It must be annotated with @Autowired so Spring can invoke it.

      @BeforeAll is a JUnit Jupiter lifecycle callback invoked by the test engine, not a Spring injection point; @Autowired has no bearing on whether it runs.

    2. B. It must be static, because with the default per-method test instance lifecycle it runs once before any test instance exists.Correct answer

      Under Jupiter's default PER_METHOD instance lifecycle a fresh test instance is created for each test, so the one-time @BeforeAll callback runs before any instance exists and must be static (or the class must switch to PER_CLASS lifecycle).

    3. C. It must return void and take the ApplicationContext as a parameter.

      A one-time setup method need not receive the ApplicationContext; Jupiter resolves parameters through registered extensions only if declared, and none is mandatory here.

    4. D. It must be named setUp() to be discovered by the Jupiter engine.

      Jupiter discovers lifecycle methods by annotation, not by a magic method name; the JUnit 4 naming convention does not apply.

    Explanation

    With JUnit Jupiter's default per-method test instance lifecycle, a new instance is created for every test method, so a once-per-class callback cannot depend on any instance and must be declared static. Switching the class to the PER_CLASS lifecycle is the alternative that allows a non-static one. The callback is discovered by its annotation rather than by a method name, and it is driven by the JUnit engine rather than by Spring injection.

  8. Question 8

    A @Transactional test method inserts rows and you want those rows to actually be committed to the database instead of the framework's default behaviour. Which annotation on the test method achieves that?

    1. A. @Rollback(true)

      @Rollback(true) explicitly restores the default rollback behaviour, so the inserted rows would still be rolled back rather than committed.

    2. B. @CommitCorrect answer

      @Commit (equivalently @Rollback(false)) overrides the automatic end-of-test rollback so the test-managed transaction commits, persisting the inserted rows.

    3. C. @DirtiesContext

      @DirtiesContext evicts the cached ApplicationContext; it has nothing to do with whether a test's transaction commits or rolls back.

    4. D. @Sql(executionPhase = AFTER_TEST_METHOD)

      @Sql runs a SQL script around the test; it does not change the commit/rollback decision for the test-managed transaction.

    Explanation

    By default the TestContext framework rolls back each @Transactional test method's transaction, and committing instead is requested with the commit annotation (or equivalently by setting rollback to false). Explicitly asking for rollback restores the default rather than committing, while context eviction and SQL-script execution are unrelated concerns.

Practise all 27 Testing Spring Applications questions

Spring Certified Professional (Develop) has the full set, inside timed mock exams that mirror real exam conditions — every question with a worked explanation.

Open Spring Certified Professional (Develop)

Other topics in this pack