CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-springframework-boot--spring-boot-starter-jooq

Starter for using jOOQ to access SQL databases with JDBC, providing auto-configuration and Spring integration

Pending
Overview
Eval results
Files

testing-integration.mddocs/

Testing Integration

Testing support for jOOQ-based components providing slice testing capabilities that focus only on jOOQ operations while excluding non-relevant Spring Boot features.

Capabilities

@JooqTest Annotation

Main test annotation for jOOQ slice testing that configures only jOOQ-related components and provides transactional test execution.

/**
 * Annotation for a jOOQ test that focuses only on jOOQ-based components.
 * Using this annotation enables auto-configuration relevant to jOOQ tests only.
 * Component scanning is configured to skip regular components and configuration properties.
 * By default uses the configured database, but can be overridden with @AutoConfigureTestDatabase.
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@BootstrapWith(JooqTestContextBootstrapper.class)
@ExtendWith(SpringExtension.class)
@OverrideAutoConfiguration(enabled = false)
@TypeExcludeFilters(JooqTypeExcludeFilter.class)
@Transactional
@AutoConfigureCache
@AutoConfigureJooq
@ImportAutoConfiguration
public @interface JooqTest {
    
    /**
     * Properties in form key=value that should be added to the Spring Environment before the test runs
     * @return the properties to add
     */
    String[] properties() default {};
    
    /**
     * Determines if default filtering should be used with @SpringBootApplication
     * By default no beans are included
     * @return if default filters should be used
     */
    boolean useDefaultFilters() default true;
    
    /**
     * A set of include filters which can be used to add otherwise filtered beans to the application context
     * @return include filters to apply
     */
    Filter[] includeFilters() default {};
    
    /**
     * A set of exclude filters which can be used to filter beans that would otherwise be added to the application context
     * @return exclude filters to apply
     */
    Filter[] excludeFilters() default {};
    
    /**
     * Auto-configuration exclusions that should be applied for this test
     * @return auto-configuration exclusions to apply
     */
    @AliasFor(annotation = ImportAutoConfiguration.class, attribute = "exclude")
    Class<?>[] excludeAutoConfiguration() default {};
}

@AutoConfigureJooq Annotation

Auto-configuration imports for typical jOOQ tests. Most tests should use @JooqTest rather than this annotation directly.

/**
 * Auto-configuration imports for typical jOOQ tests
 * Most tests should consider using @JooqTest rather than using this annotation directly
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@ImportAutoConfiguration
public @interface AutoConfigureJooq {
}

Usage Examples:

Basic jOOQ Test

@JooqTest
class UserRepositoryTest {
    
    @Autowired
    private DSLContext dsl;
    
    @Test
    void shouldFindUserById() {
        // Insert test data
        dsl.insertInto(USER)
           .set(USER.ID, 1L)
           .set(USER.NAME, "John Doe")
           .set(USER.EMAIL, "john@example.com")
           .execute();
        
        // Test query
        User user = dsl.selectFrom(USER)
                       .where(USER.ID.eq(1L))
                       .fetchOneInto(User.class);
        
        assertThat(user.getName()).isEqualTo("John Doe");
        assertThat(user.getEmail()).isEqualTo("john@example.com");
    }
    
    @Test 
    void shouldUpdateUserEmail() {
        // Setup
        dsl.insertInto(USER)
           .set(USER.ID, 1L)
           .set(USER.NAME, "Jane Doe")
           .set(USER.EMAIL, "jane@old.com")
           .execute();
        
        // Update
        int updated = dsl.update(USER)
                         .set(USER.EMAIL, "jane@new.com")
                         .where(USER.ID.eq(1L))
                         .execute();
        
        // Verify
        assertThat(updated).isEqualTo(1);
        
        String newEmail = dsl.select(USER.EMAIL)
                             .from(USER)
                             .where(USER.ID.eq(1L))
                             .fetchOne(USER.EMAIL);
        assertThat(newEmail).isEqualTo("jane@new.com");
    }
}

Test with Custom Properties

@JooqTest(properties = {
    "spring.jooq.sql-dialect=H2",
    "logging.level.org.jooq=DEBUG"
})
class ProductRepositoryTest {
    
    @Autowired
    private DSLContext dsl;
    
    @Test
    void shouldCreateProduct() {
        // Test will run with H2 dialect and jOOQ debug logging enabled
        dsl.insertInto(PRODUCT)
           .set(PRODUCT.NAME, "Test Product")
           .set(PRODUCT.PRICE, new BigDecimal("29.99"))
           .execute();
        
        Integer count = dsl.selectCount()
                           .from(PRODUCT)
                           .fetchOne(0, Integer.class);
        assertThat(count).isEqualTo(1);
    }
}

Test with Custom Configuration

@JooqTest
@TestConfiguration
class OrderServiceTest {
    
    @Autowired
    private DSLContext dsl;
    
    // Custom configuration for test
    @TestConfiguration
    static class Config {
        
        @Bean
        @Primary
        public DefaultConfigurationCustomizer testCustomizer() {
            return configuration -> {
                // Add test-specific configuration
                Settings settings = new Settings();
                settings.withExecuteLogging(true);
                configuration.set(settings);
            };
        }
    }
    
    @Test
    void shouldProcessOrder() {
        // Insert test order
        dsl.insertInto(ORDER)
           .set(ORDER.ID, 1L)
           .set(ORDER.CUSTOMER_ID, 123L)
           .set(ORDER.TOTAL, new BigDecimal("99.99"))
           .execute();
        
        // Verify order exists
        Order order = dsl.selectFrom(ORDER)
                         .where(ORDER.ID.eq(1L))
                         .fetchOneInto(Order.class);
        
        assertThat(order).isNotNull();
        assertThat(order.getTotal()).isEqualByComparingTo(new BigDecimal("99.99"));
    }
}

Test with Embedded Database

@JooqTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.ANY)
class InMemoryDatabaseTest {
    
    @Autowired
    private DSLContext dsl;
    
    @Test
    void shouldWorkWithEmbeddedDatabase() {
        // This test will use an embedded in-memory database
        // instead of the configured production database
        
        dsl.insertInto(CUSTOMER)
           .set(CUSTOMER.NAME, "Test Customer")
           .set(CUSTOMER.EMAIL, "test@example.com")
           .execute();
        
        List<Customer> customers = dsl.selectFrom(CUSTOMER)
                                      .fetchInto(Customer.class);
        
        assertThat(customers).hasSize(1);
        assertThat(customers.get(0).getName()).isEqualTo("Test Customer");
    }
}

Testing Exception Handling

@JooqTest
class ExceptionHandlingTest {
    
    @Autowired
    private DSLContext dsl;
    
    @Test
    void shouldHandleDuplicateKeyException() {
        // Insert initial record
        dsl.insertInto(USER)
           .set(USER.EMAIL, "unique@example.com")
           .set(USER.NAME, "First User")
           .execute();
        
        // Attempt duplicate insert - should throw Spring exception
        assertThatThrownBy(() ->
            dsl.insertInto(USER)
               .set(USER.EMAIL, "unique@example.com")  // Duplicate email
               .set(USER.NAME, "Second User")
               .execute()
        ).isInstanceOf(DuplicateKeyException.class);
    }
    
    @Test
    void shouldHandleConstraintViolation() {
        // Test constraint violations are properly translated
        assertThatThrownBy(() ->
            dsl.insertInto(USER)
               .set(USER.EMAIL, "invalid-email-format")  // Violates email constraint
               .set(USER.NAME, "Test User")
               .execute()
        ).isInstanceOf(DataIntegrityViolationException.class);
    }
}

Test Infrastructure Components

JooqTestContextBootstrapper

Test context bootstrapper specifically for jOOQ tests that ensures proper test slice configuration.

/**
 * BootstrapContext for @JooqTest based tests
 * Ensures proper test slice configuration for jOOQ-only testing
 */
class JooqTestContextBootstrapper extends SpringBootTestContextBootstrapper {
    
    /**
     * Get the configuration classes for the test context
     * @param testClass the test class being bootstrapped
     * @return array of configuration classes
     */
    @Override
    protected Class<?>[] getOrFindConfigurationClasses(Class<?> testClass);
}

JooqTypeExcludeFilter

Type filter that excludes non-jOOQ components during test context loading to ensure slice testing focuses only on jOOQ functionality.

/**
 * TypeExcludeFilter for @JooqTest
 * Excludes non-jOOQ components to ensure slice testing
 */
class JooqTypeExcludeFilter extends AnnotationCustomizableTypeExcludeFilter {
    
    /**
     * Constructor taking the test class
     * @param testClass the test class to configure filtering for
     */
    JooqTypeExcludeFilter(Class<?> testClass);
}

Key Testing Features

Transactional Test Execution

  • All @JooqTest annotated tests run within a transaction by default
  • Transactions are automatically rolled back after each test method
  • Ensures test isolation and prevents test data pollution

Slice Testing

  • Only loads jOOQ-related Spring Boot auto-configuration
  • Excludes web layer, security, messaging, and other non-database components
  • Faster test startup and execution compared to full integration tests

Database Configuration

  • Uses the application's configured DataSource by default
  • Can be overridden with @AutoConfigureTestDatabase for embedded databases
  • Supports all database types supported by jOOQ and Spring Boot

Exception Translation

  • Full exception translation is active during tests
  • JDBC and jOOQ exceptions are translated to Spring's DataAccessException hierarchy
  • Consistent exception handling testing with production code

Install with Tessl CLI

npx tessl i tessl/maven-org-springframework-boot--spring-boot-starter-jooq

docs

auto-configuration.md

configuration.md

exception-handling.md

index.md

testing-integration.md

transaction-integration.md

tile.json