Software Testing

Software Testing

Code Coverage

Java

JUnit

JUnit - Extension

JUnit - Parallel Execution

Mockito

  • When shoud you use mock or spy

    If you want to be safe and avoid calling external services and just want to test the logic inside of the unit, then use mock.

    If you want to call external service and perform calling of real dependency, or simply say, you want to run the program as it is and just stub specific methods, then use spy.

  • Resources

Initialize objects annotated with Mockito annotations

Including @Mock, @Spy, @InjectMocks and @Captor.

  • Use @ExtendWith(MockitoExtension.class) to enable Mockito annotations in JUnit 5 tests.

or

  • Programatically

    @BeforeAll
    void beforeAll() {
      MockitoAnnotations.openMocks(this);
    }

@Mock

  • Use @Mock to create a mock object.

@Spy

  • Use @Spy to create a spy object.

@InjectMocks

  • Use @InjectMocks to inject mocks (objects annotated with @Mock) or spies (objects annotated with @Spy) into the annotated field, but the object itself is not mocked or spied.

Awaitility

Replace Thread.sleep()

Awaitility.await()
        .timeout(6, TimeUnit.SECONDS)
        .pollDelay(5, TimeUnit.SECONDS)
        .untilAsserted(() -> producer.partitionsFor(record.topic()));

Spring Test

Unit Testing

  • MockMvc is used to test the controller layer without needing a real HTTP server.
  • @WebMvcTest is used to test the controller layer with only the controller layer.
  • Use @DataJpaTest to test repositories with an embedded database.
@TestConfiguration
  • Use @TestConfiguration to provide additional beans for testing.
  • Create a static nested class in the same test class where we want to autowire the bean.
  • Create a separate test configuration class and import it using the @Import annotation.
@TestPropertySource
  • Use @TestPropertySource to set configuration properties for tests.

    @TestPropertySource(properties = {
        "spring.datasource.url=jdbc:h2:mem:test",
        "spring.datasource.driverClassName=org.h2.Driver",
        "spring.datasource.username=root",
        "spring.datasource.password=secret",
        "spring.flyway.enabled=false"
    })

    Alternatively, use @SpringBootTest to set configuration properties for tests.

    @SpringBootTest(properties = {
        "spring.datasource.url=jdbc:h2:mem:test",
        "spring.datasource.driverClassName=org.h2.Driver",
        "spring.datasource.username=root",
        "spring.datasource.password=secret",
        "spring.flyway.enabled=false"
    })
@DynamicPropertySource
  • Use @DynamicPropertySource to set dynamic configuration properties for tests.

    @DynamicPropertySource
    static void kafkaProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.kafka.bootstrap-servers", kafkaContainer::getBootstrapServers);
    }
  • @DynamicPropertySource have higher precedence than those loaded from @TestPropertySource, the operating system's environment variables, Java system properties, or property sources added by the application declaratively by using @PropertySource or programmatically. Thus, dynamic properties can be used to selectively override properties loaded via @TestPropertySource, system property sources, and application property sources.

@DirtiesContext
  • Use @DirtiesContext to reset the Spring context after a test.
@MockBean / @MockitoBean
  • Mocked bean in a Spring ApplicationContext
  • Deprecated in favor of @MockitoBean since Spring Boot 3.4
@SpyBean / @MockitoSpyBean
  • @SpyBean from Spring Test, is used to create a real Spring bean (if it’s not already defined as a bean) and then spy on it.
  • An object will behave like an @Autowired object.
  • All its methods will actually work, but we can define some custom behavior for its methods.
  • Use doReturn(...) / doNothing(...) to add custom (mocked) method behaviour
  • Use if you want to provide your mock behaviour but not dismiss entirely its normal behaviour
  • Deprecated in favor of @MockitoSpyBean since Spring Boot 3.4

Integration Testing

  • @SpringBootTest is used to test the service layer with a real HTTP server.
  • @DataJpaTest is used to test the repository layer with an in-memory database.
  • TestRestTemplate is used to test the controller layer with a real HTTP server, and you can also use RestAssured to test the controller layer.