Skip to Content
⭐️ If you like FlowInquiry, consider supporting the project by giving it a star on GitHub !
Developer GuidesBackendIntegration Testing

Integration Testing Guidelines

Integration tests are critical for ensuring that your FlowInquiry backend components work together correctly. This guide covers how to write effective integration tests using TestContainers in the FlowInquiry ecosystem.

Benefits of Using TestContainers

TestContainers  provides lightweight, disposable containers for your integration tests, offering several advantages:

  • Realistic testing environment: Tests run against actual databases and services instead of mocks
  • Consistency across environments: The same containers run in CI/CD pipelines and local development
  • Isolation: Each test suite can use its own containerized dependencies
  • Parallel test execution: TestContainers supports concurrent testing
  • Simplified setup: No need to maintain external test infrastructure
  • Comprehensive coverage: Test the full stack, including database interactions and external services

Writing Integration Tests in FlowInquiry

Test Data Management

FlowInquiry gets test data from the module tools/liquibase, and all test data files are located at the data/test folder. This provides an elegant way to handle test data:

  1. Test data files are organized in the data/test folder
  2. The tools/liquibase module manages these test data files
  3. Add the context="test" attribute to changesets containing test data:
<changeSet id="create-test-users" author="developer" context="test"> <insert tableName="users"> <column name="id" value="test-user-1"/> <column name="username" value="testuser"/> <column name="email" value="test@example.com"/> </insert> </changeSet>
  1. These test changesets will only be applied during integration tests, keeping your development and production databases clean

Changeset for project table

<changeSet author="flowinquiry" id="000:07-insert-default-fw-project-data" runOnChange="true"> <loadData file="config/liquibase/tenant/data/test/fw_project_test.csv" tableName="fw_project" separator=";"> <column name="id" type="NUMERIC" /> <column name="created_by" type="NUMERIC" /> <column name="created_at" type="TIMESTAMP" /> <column name="modified_by" type="NUMERIC" /> <column name="modified_at" type="TIMESTAMP" /> <column name="name" type="STRING" /> <column name="description" type="STRING" /> <column name="short_name" type="STRING" /> <column name="team_id" type="NUMERIC" /> <column name="status" type="STRING" /> <column name="start_date" type="TIMESTAMP" /> <column name="end_date" type="TIMESTAMP" /> </loadData> <sql>SELECT setval('fw_project_id_seq', (SELECT MAX(id) FROM fw_project));</sql> </changeSet>

CSV Test Data Example

Test data files are typically stored in CSV format with semicolon (;) separators. Here’s an example from fw_project_test.csv, which reflects the project table in the database:

id;created_by;created_at;modified_by;modified_at;name;description;short_name;team_id;status;start_date;end_date 1;1;2023-01-01T10:00:00;1;2023-01-01T10:00:00;Customer Portal;Customer-facing web portal;cust;1;Active;2023-01-02T00:00:00;2023-06-30T00:00:00 2;1;2023-01-05T09:30:00;1;2023-01-05T09:30:00;CRM System;Manage contacts and leads;crm;2;Active;2023-01-10T00:00:00;2023-07-31T00:00:00

Each column in the CSV file has a specific meaning:

  • id: Unique identifier for the project
  • created_by: User ID who created the project
  • created_at: Timestamp when the project was created
  • modified_by: User ID who last modified the project
  • modified_at: Timestamp when the project was last modified
  • name: Full name of the project
  • description: Detailed description of the project
  • short_name: Abbreviated name/code for the project
  • team_id: ID of the team responsible for the project
  • status: Current status of the project (e.g., “Active”)
  • start_date: Project start date
  • end_date: Project end date

Writing Integration Tests

To create an integration test in FlowInquiry:

  1. Create a test class in the src/test/java directory
  2. Annotate the class with @IntegrationTest:
@IntegrationTest @Transactional public class TicketServiceIT { @Autowired private UserService userService; ... @Test void shouldCreateTicketSuccessfully() { TicketDTO ticketDTO = ticketMapper.toDto(ticketRepository.findById(2L).orElseThrow()); ticketDTO.setId(null); ticketDTO.setConversationHealth(null); TicketDTO savedTicket = ticketService.createTicket(ticketDTO); assertThat(savedTicket).isNotNull(); ArgumentCaptor<NewTicketCreatedEvent> eventCaptor = ArgumentCaptor.forClass(NewTicketCreatedEvent.class); verify(spyEventPublisher, times(1)).publishEvent(eventCaptor.capture()); } }

The @IntegrationTest annotation handles:

  • Starting the required containers (PostgreSQL, Redis, etc.)
  • Applying database migrations with test context
  • Configuring Spring to use the containerized services
  • Cleaning up after tests complete

Running Integration Tests

Running in IDE

To run integration tests in your IDE:

  1. Make sure you have Docker installed and running
  2. Right-click on the test class and select “Run as JUnit Test”
  3. If you want to debug, right-click and choose “Debug as JUnit Test”

Most popular IDEs (IntelliJ IDEA, Eclipse, VS Code) support running these tests directly.

Running with Gradle

To run integration tests using Gradle:

./gradlew integrationTest

This will:

  1. Start the required Docker containers
  2. Execute all tests annotated with @IntegrationTest
  3. Generate test reports in the apps/server/build/reports/jacoco directory
  4. Shut down and clean up containers after completion

If you want to run a specific integration test class:

./gradlew integrationTest --tests "io.flowinquiry.modules.teams.service.TicketServiceIT"
Last updated on