Skip to content

Commit

Permalink
Add integration tests for PagingQueryProvider
Browse files Browse the repository at this point in the history
Adds testcontainers based tests for DB2, MySQL, MariaDB, Postgres, Sql Server and Oracle Database, as well as standard tests for HSQL and SQLite.
  • Loading branch information
hpoettker authored and fmbenhassine committed Dec 10, 2024
1 parent 8f1b24a commit b831a7d
Show file tree
Hide file tree
Showing 11 changed files with 690 additions and 66 deletions.
78 changes: 78 additions & 0 deletions spring-batch-infrastructure/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,84 @@
<version>${derby.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${testcontainers.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>${mysql-connector-j.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>mysql</artifactId>
<version>${testcontainers.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>oracle-xe</artifactId>
<version>${testcontainers.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc10</artifactId>
<version>${oracle.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>${mariadb-java-client.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>mariadb</artifactId>
<version>${testcontainers.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgresql.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>postgresql</artifactId>
<version>${testcontainers.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.ibm.db2</groupId>
<artifactId>jcc</artifactId>
<version>${db2.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>db2</artifactId>
<version>${testcontainers.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>mssqlserver</artifactId>
<version>${testcontainers.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>${sqlserver.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Copyright 2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.item.database.support;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;

import org.junit.jupiter.api.Test;
import org.springframework.batch.item.database.Order;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

import static org.junit.jupiter.api.Assertions.assertEquals;

/**
* @author Henning Pöttker
*/
abstract class AbstractPagingQueryProviderIntegrationTests {

private final JdbcTemplate jdbcTemplate;

private final AbstractSqlPagingQueryProvider queryProvider;

AbstractPagingQueryProviderIntegrationTests(DataSource dataSource, AbstractSqlPagingQueryProvider queryProvider) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.queryProvider = queryProvider;
}

@Test
void testWithoutGrouping() {
queryProvider.setSelectClause("ID, STRING");
queryProvider.setFromClause("TEST_TABLE");
Map<String, Order> sortKeys = new HashMap<>();
sortKeys.put("ID", Order.ASCENDING);
queryProvider.setSortKeys(sortKeys);

List<Item> firstPage = jdbcTemplate.query(queryProvider.generateFirstPageQuery(2), MAPPER);
assertEquals(List.of(new Item(1, "Spring"), new Item(2, "Batch")), firstPage);

List<Item> secondPage = jdbcTemplate.query(queryProvider.generateRemainingPagesQuery(2), MAPPER, 2);
assertEquals(List.of(new Item(3, "Infrastructure")), secondPage);
}

@Test
void testWithGrouping() {
queryProvider.setSelectClause("STRING");
queryProvider.setFromClause("GROUPING_TEST_TABLE");
queryProvider.setGroupClause("STRING");
Map<String, Order> sortKeys = new HashMap<>();
sortKeys.put("STRING", Order.ASCENDING);
queryProvider.setSortKeys(sortKeys);

List<String> firstPage = jdbcTemplate.queryForList(queryProvider.generateFirstPageQuery(2), String.class);
assertEquals(List.of("Batch", "Infrastructure"), firstPage);

List<String> secondPage = jdbcTemplate.queryForList(queryProvider.generateRemainingPagesQuery(2), String.class,
"Infrastructure");
assertEquals(List.of("Spring"), secondPage);
}

private record Item(Integer id, String string) {
}

private static final RowMapper<Item> MAPPER = (rs, rowNum) -> new Item(rs.getInt("id"), rs.getString("string"));

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright 2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.item.database.support;

import javax.sql.DataSource;

import com.ibm.db2.jcc.DB2SimpleDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.jdbc.Sql;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import org.testcontainers.containers.Db2Container;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.utility.DockerImageName;

import static org.springframework.test.context.jdbc.Sql.ExecutionPhase.BEFORE_TEST_CLASS;

/**
* @author Henning Pöttker
*/
@Testcontainers(disabledWithoutDocker = true)
@SpringJUnitConfig
@Sql(scripts = "query-provider-fixture.sql", executionPhase = BEFORE_TEST_CLASS)
class Db2PagingQueryProviderIntegrationTests extends AbstractPagingQueryProviderIntegrationTests {

// TODO find the best way to externalize and manage image versions
private static final DockerImageName DB2_IMAGE = DockerImageName.parse("ibmcom/db2:11.5.5.1");

@Container
public static Db2Container db2 = new Db2Container(DB2_IMAGE).acceptLicense();

Db2PagingQueryProviderIntegrationTests(@Autowired DataSource dataSource) {
super(dataSource, new Db2PagingQueryProvider());
}

@Configuration
static class TestConfiguration {

@Bean
public DataSource dataSource() throws Exception {
DB2SimpleDataSource dataSource = new DB2SimpleDataSource();
dataSource.setDatabaseName(db2.getDatabaseName());
dataSource.setUser(db2.getUsername());
dataSource.setPassword(db2.getPassword());
dataSource.setDriverType(4);
dataSource.setServerName(db2.getHost());
dataSource.setPortNumber(db2.getMappedPort(Db2Container.DB2_PORT));
dataSource.setSslConnection(false);
return dataSource;
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,84 +15,36 @@
*/
package org.springframework.batch.item.database.support;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.springframework.batch.item.database.Order;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;

import static org.junit.jupiter.api.Assertions.assertEquals;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;

/**
* @author Henning Pöttker
*/
class DerbyPagingQueryProviderIntegrationTests {

private static EmbeddedDatabase embeddedDatabase;

private static JdbcTemplate jdbcTemplate;

@BeforeAll
static void setUp() {
embeddedDatabase = new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.DERBY)
.addScript("/org/springframework/batch/item/database/support/query-provider-fixture.sql")
.generateUniqueName(true)
.build();
jdbcTemplate = new JdbcTemplate(embeddedDatabase);
}

@AfterAll
static void tearDown() {
if (embeddedDatabase != null) {
embeddedDatabase.shutdown();
}
}

@Test
void testWithoutGrouping() {
var queryProvider = new DerbyPagingQueryProvider();
queryProvider.setSelectClause("ID, STRING");
queryProvider.setFromClause("TEST_TABLE");
Map<String, Order> sortKeys = new HashMap<>();
sortKeys.put("ID", Order.ASCENDING);
queryProvider.setSortKeys(sortKeys);
@SpringJUnitConfig
class DerbyPagingQueryProviderIntegrationTests extends AbstractPagingQueryProviderIntegrationTests {

List<Item> firstPage = jdbcTemplate.query(queryProvider.generateFirstPageQuery(2), MAPPER);
assertEquals(List.of(new Item(1, "Spring"), new Item(2, "Batch")), firstPage);

List<Item> secondPage = jdbcTemplate.query(queryProvider.generateRemainingPagesQuery(2), MAPPER, 2);
assertEquals(List.of(new Item(3, "Infrastructure")), secondPage);
DerbyPagingQueryProviderIntegrationTests(@Autowired DataSource dataSource) {
super(dataSource, new DerbyPagingQueryProvider());
}

@Test
void testWithGrouping() {
var queryProvider = new DerbyPagingQueryProvider();
queryProvider.setSelectClause("STRING");
queryProvider.setFromClause("GROUPING_TEST_TABLE");
queryProvider.setGroupClause("STRING");
Map<String, Order> sortKeys = new HashMap<>();
sortKeys.put("STRING", Order.ASCENDING);
queryProvider.setSortKeys(sortKeys);

List<String> firstPage = jdbcTemplate.queryForList(queryProvider.generateFirstPageQuery(2), String.class);
assertEquals(List.of("Batch", "Infrastructure"), firstPage);
@Configuration
static class TestConfiguration {

List<String> secondPage = jdbcTemplate.queryForList(queryProvider.generateRemainingPagesQuery(2), String.class,
"Infrastructure");
assertEquals(List.of("Spring"), secondPage);
}
@Bean
public DataSource dataSource() throws Exception {
return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.DERBY)
.addScript("/org/springframework/batch/item/database/support/query-provider-fixture.sql")
.generateUniqueName(true)
.build();
}

private record Item(Integer id, String string) {
}

private static final RowMapper<Item> MAPPER = (rs, rowNum) -> new Item(rs.getInt("id"), rs.getString("string"));

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.item.database.support;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;

/**
* @author Henning Pöttker
*/
@SpringJUnitConfig
class HsqlPagingQueryProviderIntegrationTests extends AbstractPagingQueryProviderIntegrationTests {

HsqlPagingQueryProviderIntegrationTests(@Autowired DataSource dataSource) {
super(dataSource, new HsqlPagingQueryProvider());
}

@Configuration
static class TestConfiguration {

@Bean
public DataSource dataSource() throws Exception {
return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL)
.addScript("/org/springframework/batch/item/database/support/query-provider-fixture.sql")
.generateUniqueName(true)
.build();
}

}

}
Loading

0 comments on commit b831a7d

Please sign in to comment.