Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

An IntegrationTest in Geode is a test involving inter-operation of components or subsystems.

  • Should use JUnit 4 syntax
  • File name ends with *IntegrationTest
  • Should use Category annotation of type IntegrationTest
  • May take longer than a UnitTest but should generally complete in seconds
  • May test a single class or any combination of classes including end-to-end testing of Geode
  • Typically uses black-box testing but may include some white-box testing and helps guarantee external quality (feature delivers value to User)
  • An IntegrationTest may do any of the following:
    • communicate across the network
    • access the file system
    • require anything special in the environment (such as editing config files or running an external process)
  • Good examples in Geode:
    • RegionExpirationIntegrationTest

You would typically write an IntegrationTest if you want to test the interaction of real dependencies in a class or if you want to perform functional testing of any feature that requires more than a single class. Any testing that requires any kind of file access or networking should be done in an IntegrationTest instead of a UnitTest. Most of our IntegrationTests use either the file system or create an actual Cache for functional testing.

If you write an IntegrationTest to expose a bug and then confirm its fix, then you should name it with the suffix *RegressionTest. Otherwise you should use the suffix *IntegrationTest.

Preferred Testing Frameworks and Libraries for Geode IntegrationTests

Overall Framework

  • JUnit 4 (including Rules)
  • Paramerized – JUnit 4.12 has a bug which prevents Parameterized and Category from working together properly
    • Please use CategoryWithParameterizedRunnerFactory from Geode when using Parameterized (see GEODE-1350)
  • TemporaryFolder – provides isolated file system that will be cleaned up after the test
  • TestName – provides name of the test method currently being tested
  • ErrorCollector – use this when performing assertions in callbacks such as CacheListener

Assertion Library

  • AssertJ – richer API with better failure messages than JUnit 4 Assert

Mocking Library

  • Mockito
  • PowerMock – use this as a last resort – refactoring code to facilitate better testing is preferred

Expected Exceptions

  • Use AssertJ or Catch-Exception instead of JUnit 4 Rule ExpectedException
  • AssertJ (assertThatThrownBy) – this is the cleanest and preferred way to test for expected exception
  • Catch-Exception – better support for complex nesting of exceptions or exceptions with unusual APIs

Additional 3rd Party Libraries for UnitTests

  • JUnitParams – provides test method parameterization (usually better to use than JUnit 4 Parameterized)
  • System Rules – powerful set of JUnit 4 Rules
    • RestoreSystemProperties
  • Awaitility – useful for awaiting asynchronous conditions

Custom Geode JUnit 4 Rules and Testing Tools

  • ExecutorServiceRule – provides ExecutorService for concurrent testing
  • ExpectedTimeoutRule – verifies that an API times out and potentially throws TimeoutException
  • JarFileRule – creates a Jar file in an internal TemporaryFolder containing a dynamically generated class
  • RequiresGeodeHome – asserts precondition that GEODE_HOME system property is specified
  • RestoreLocaleRule – restores JVM to original Locale
  • RestoreTCCLRule – restores Thread Context Class Loader
  • RetryRule – retries a test until it passes or exceeds specified number of retries
  • TemporaryFileRule – destroys specified files or directories that aren't created in a TemporaryFolder
  • UseJacksonForJsonPathRule – specifies that JsonPath should use Jackson instead of its default JSON library
  • GfshRule – allows use of Gfsh script string to fork a JVM process in an IntegrationTest

Examples of actual tests

Examples of some good IntegrationTests:

  • RegionExpirationIntegrationTest.java

Examples of good RegressionTests which are IntegrationTests:

  • StatArchiveWithMissingResourceTypeRegressionTest

General form of a IntegrationTest:

Code Block
package org.apache.geode.internal.cache.backup;
 
import static org.assertj.core.api.Assertions.assertThat;
 
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;

import org.apache.geode.test.junit.categories.IntegrationTest.class
 
@Category(IntegrationTest.class)
public class BackupIncrementalWithMissingBaselineRegressionTest {
  
  @Rule
  public TemporaryFolder temporaryFolder = new TemporaryFolder();
 
  @Before
  public void setUp() {
    // arrange: create the SUT (system under test) and its dependencies
    // use JUnit 4 TemporaryFolder for any file system use
  }
 
  @Test
  public void incrementalBackupWithMissingBaselineThrows() {
    // act: attempt incremental backup with missing baseline directory
    // assert: verify thrown exception is not NullPointerException with correct message
  }
}