Spring Framework Testing Concepts

From NovaOrdis Knowledge Base
Jump to navigation Jump to search

External

Internal

Overview

Proper deployment of dependency injection makes both unit and integration testing easier, in that the presence of setter methods and appropriate constructors on classes makes them easier to wire together in a test without having to set up service locator registries or similar structures.

Unit Tests

According to Spring reference documentation, a Spring unit test is a test that does not use a real application context. The unit test should work without such a real application context, and use objects created with the new operator and injected with a direct invocation of the constructor or setter methods.

Spring provides MockEnvironment and MockPropertySource that are useful for developing out-of-container tests. Understand this.

Integration Tests

According to Spring reference documentation, a Spring integration test is a test where dependencies are injected with the help of a real application context, albeit a special, test-oriented implementation of it. Yet, these tests do not rely on the presence of an application server or Spring Boot instance, or a deployment environment. These tests are slower to run than unit tests, but much faster than the equivalent Selenium or remote tests, that rely on deployment in an actual deployment environment.

Spring provides an integration testing framework, named Spring TestContext Framework. The framework is annotation-driven, and aims to provide the following:

  • Context management and caching between tests. This generally speeds up successive tests.
  • Dependency injection of test fixture instances.
  • Transaction management. The tests can be coded assuming existence of a transaction.
  • Spring-specific base classes.

Spring TestContext Framework Dependency

dependencies {
    testImplementation('org.springframework:spring-test')
}

This dependency declaration assumes that we are using Gradle Spring dependency-management Plugin and a Maven BOM.

Integration Test Programming Model

Spring TestContext Framework requires a specialized test runner, implemented by the SpringRunner class. The SpringRunner class is an extension of JUnit's BlockJUnit4ClassRunner, which provides functionality of the Spring TestContext Framework to standard JUnit tests. The essential piece of the SpringRunner is a TestContextManager instance, which manages a

* single {@link TestContext} and signaling events to all registered
* {@link TestExecutionListener TestExecutionListeners} at the following test
* execution points:
*

*

    *
  • {@link #beforeTestClass() before test class execution}: prior to any * before class callbacks of a particular testing framework (e.g., * JUnit 4's {@link org.junit.BeforeClass @BeforeClass})
  • *
  • {@link #prepareTestInstance test instance preparation}: * immediately following instantiation of the test class
  • *
  • {@link #beforeTestMethod before test setup}: * prior to any before method callbacks of a particular testing framework * (e.g., JUnit 4's {@link org.junit.Before @Before})
  • *
  • {@link #beforeTestExecution before test execution}: * immediately before execution of the {@linkplain java.lang.reflect.Method * test method} but after test setup
  • *
  • {@link #afterTestExecution after test execution}: * immediately after execution of the {@linkplain java.lang.reflect.Method * test method} but before test tear down
  • *
  • {@link #afterTestMethod(Object, Method, Throwable) after test tear down}: * after any after method callbacks of a particular testing * framework (e.g., JUnit 4's {@link org.junit.After @After})
  • *
  • {@link #afterTestClass() after test class execution}: after any * after class callbacks of a particular testing framework (e.g., JUnit 4's * {@link org.junit.AfterClass @AfterClass})
  • *
*

*

Support for loading and accessing * {@linkplain org.springframework.context.ApplicationContext application contexts}, * dependency injection of test instances, * {@linkplain org.springframework.transaction.annotation.Transactional transactional} * execution of test methods, etc. is provided by * {@link SmartContextLoader ContextLoaders} and {@link TestExecutionListener * TestExecutionListeners}, which are configured via * {@link ContextConfiguration @ContextConfiguration} and * {@link TestExecutionListeners @TestExecutionListeners}. * *

Bootstrapping of the {@code TestContext}, the default {@code ContextLoader}, * default {@code TestExecutionListeners}, and their collaborators is performed * by a {@link TestContextBootstrapper}, which is configured via * {@link BootstrapWith @BootstrapWith}. * * @author Sam Brannen

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 = {AComponent.class})
public class AComponentIntegrationTests {

    @Autowired
    private AComponent aComponent;

    @Test
    public void realContextInjectsComponent() {
        assertNotNull(aComponent);
    }
}

@RunWith

Annotations