Add nullability annotations to tests in module/spring-boot-jdbc

See gh-47263
This commit is contained in:
Moritz Halbritter 2025-09-26 15:29:33 +02:00
parent 34a8e1bd82
commit e4a58a53d0
31 changed files with 148 additions and 75 deletions

View File

@ -77,6 +77,8 @@ dependencies {
} }
testImplementation("tools.jackson.core:jackson-databind") testImplementation("tools.jackson.core:jackson-databind")
testCompileOnly("org.checkerframework:checker-qual")
testRuntimeOnly("ch.qos.logback:logback-classic") testRuntimeOnly("ch.qos.logback:logback-classic")
testRuntimeOnly("com.clickhouse:clickhouse-jdbc") testRuntimeOnly("com.clickhouse:clickhouse-jdbc")
testRuntimeOnly("com.mysql:mysql-connector-j") testRuntimeOnly("com.mysql:mysql-connector-j")
@ -102,3 +104,11 @@ tasks.named("checkSpringConfigurationMetadata").configure {
"spring.datasource.tomcat.*", "spring.datasource.tomcat.*",
] ]
} }
tasks.named("compileTestJava") {
options.nullability.checking = "tests"
}
tasks.named("compileDockerTestJava") {
options.nullability.checking = "tests"
}

View File

@ -56,7 +56,9 @@ class ClickHouseJdbcDockerComposeConnectionDetailsFactoryIntegrationTests {
dataSource.setDriverClass((Class<? extends Driver>) ClassUtils.forName(connectionDetails.getDriverClassName(), dataSource.setDriverClass((Class<? extends Driver>) ClassUtils.forName(connectionDetails.getDriverClassName(),
getClass().getClassLoader())); getClass().getClassLoader()));
JdbcTemplate template = new JdbcTemplate(dataSource); JdbcTemplate template = new JdbcTemplate(dataSource);
assertThat(template.queryForObject(DatabaseDriver.CLICKHOUSE.getValidationQuery(), Integer.class)).isEqualTo(1); String validationQuery = DatabaseDriver.CLICKHOUSE.getValidationQuery();
assertThat(validationQuery).isNotNull();
assertThat(template.queryForObject(validationQuery, Integer.class)).isEqualTo(1);
} }
} }

View File

@ -53,8 +53,9 @@ class OracleFreeJdbcDockerComposeConnectionDetailsFactoryIntegrationTests {
getClass().getClassLoader())); getClass().getClassLoader()));
Awaitility.await().atMost(Duration.ofMinutes(1)).ignoreExceptions().untilAsserted(() -> { Awaitility.await().atMost(Duration.ofMinutes(1)).ignoreExceptions().untilAsserted(() -> {
JdbcTemplate template = new JdbcTemplate(dataSource); JdbcTemplate template = new JdbcTemplate(dataSource);
assertThat(template.queryForObject(DatabaseDriver.ORACLE.getValidationQuery(), String.class)) String validationQuery = DatabaseDriver.ORACLE.getValidationQuery();
.isEqualTo("Hello"); assertThat(validationQuery).isNotNull();
assertThat(template.queryForObject(validationQuery, String.class)).isEqualTo("Hello");
}); });
} }

View File

@ -57,8 +57,9 @@ class OracleXeJdbcDockerComposeConnectionDetailsFactoryIntegrationTests {
getClass().getClassLoader())); getClass().getClassLoader()));
Awaitility.await().atMost(Duration.ofMinutes(1)).ignoreExceptions().untilAsserted(() -> { Awaitility.await().atMost(Duration.ofMinutes(1)).ignoreExceptions().untilAsserted(() -> {
JdbcTemplate template = new JdbcTemplate(dataSource); JdbcTemplate template = new JdbcTemplate(dataSource);
assertThat(template.queryForObject(DatabaseDriver.ORACLE.getValidationQuery(), String.class)) String validationQuery = DatabaseDriver.ORACLE.getValidationQuery();
.isEqualTo("Hello"); assertThat(validationQuery).isNotNull();
assertThat(template.queryForObject(validationQuery, String.class)).isEqualTo("Hello");
}); });
} }

View File

@ -18,6 +18,8 @@ package org.springframework.boot.jdbc.docker.compose;
import java.sql.Driver; import java.sql.Driver;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.docker.compose.service.connection.test.DockerComposeTest; import org.springframework.boot.docker.compose.service.connection.test.DockerComposeTest;
import org.springframework.boot.jdbc.DatabaseDriver; import org.springframework.boot.jdbc.DatabaseDriver;
import org.springframework.boot.jdbc.autoconfigure.JdbcConnectionDetails; import org.springframework.boot.jdbc.autoconfigure.JdbcConnectionDetails;
@ -72,12 +74,13 @@ class PostgresJdbcDockerComposeConnectionDetailsFactoryIntegrationTests {
} }
private void checkDatabaseAccess(JdbcConnectionDetails connectionDetails) throws ClassNotFoundException { private void checkDatabaseAccess(JdbcConnectionDetails connectionDetails) throws ClassNotFoundException {
assertThat(executeQuery(connectionDetails, DatabaseDriver.POSTGRESQL.getValidationQuery(), Integer.class)) String validationQuery = DatabaseDriver.POSTGRESQL.getValidationQuery();
.isEqualTo(1); assertThat(validationQuery).isNotNull();
assertThat(executeQuery(connectionDetails, validationQuery, Integer.class)).isEqualTo(1);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private <T> T executeQuery(JdbcConnectionDetails connectionDetails, String sql, Class<T> resultClass) private <T> @Nullable T executeQuery(JdbcConnectionDetails connectionDetails, String sql, Class<T> resultClass)
throws ClassNotFoundException { throws ClassNotFoundException {
SimpleDriverDataSource dataSource = new SimpleDriverDataSource(); SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
dataSource.setUrl(connectionDetails.getJdbcUrl()); dataSource.setUrl(connectionDetails.getJdbcUrl());

View File

@ -68,7 +68,9 @@ class SqlServerJdbcDockerComposeConnectionDetailsFactoryIntegrationTests {
dataSource.setDriverClass((Class<? extends Driver>) ClassUtils.forName(connectionDetails.getDriverClassName(), dataSource.setDriverClass((Class<? extends Driver>) ClassUtils.forName(connectionDetails.getDriverClassName(),
getClass().getClassLoader())); getClass().getClassLoader()));
JdbcTemplate template = new JdbcTemplate(dataSource); JdbcTemplate template = new JdbcTemplate(dataSource);
assertThat(template.queryForObject(DatabaseDriver.SQLSERVER.getValidationQuery(), Integer.class)).isEqualTo(1); String validationQuery = DatabaseDriver.SQLSERVER.getValidationQuery();
assertThat(validationQuery).isNotNull();
assertThat(template.queryForObject(validationQuery, Integer.class)).isEqualTo(1);
} }
} }

View File

@ -60,7 +60,9 @@ class JdbcContainerConnectionDetailsFactoryTests {
void connectionCanBeMadeToJdbcContainer() { void connectionCanBeMadeToJdbcContainer() {
assertThat(this.connectionDetails).isNotNull(); assertThat(this.connectionDetails).isNotNull();
JdbcTemplate jdbc = new JdbcTemplate(this.dataSource); JdbcTemplate jdbc = new JdbcTemplate(this.dataSource);
assertThatNoException().isThrownBy(() -> jdbc.execute(DatabaseDriver.POSTGRESQL.getValidationQuery())); String validationQuery = DatabaseDriver.POSTGRESQL.getValidationQuery();
assertThat(validationQuery).isNotNull();
assertThatNoException().isThrownBy(() -> jdbc.execute(validationQuery));
} }
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)

View File

@ -49,6 +49,7 @@ class DataSourceBuilderRuntimeHintsTests {
TypeHint typeHint = hints.getTypeHint(dataSourceType); TypeHint typeHint = hints.getTypeHint(dataSourceType);
assertThat(typeHint).withFailMessage(() -> "No hints found for data source type " + dataSourceType) assertThat(typeHint).withFailMessage(() -> "No hints found for data source type " + dataSourceType)
.isNotNull(); .isNotNull();
assertThat(typeHint).isNotNull();
Set<MemberCategory> memberCategories = typeHint.getMemberCategories(); Set<MemberCategory> memberCategories = typeHint.getMemberCategories();
assertThat(memberCategories).containsExactly(MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS); assertThat(memberCategories).containsExactly(MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS);
}); });

View File

@ -39,6 +39,7 @@ import oracle.ucp.jdbc.PoolDataSourceImpl;
import org.apache.commons.dbcp2.BasicDataSource; import org.apache.commons.dbcp2.BasicDataSource;
import org.h2.Driver; import org.h2.Driver;
import org.h2.jdbcx.JdbcDataSource; import org.h2.jdbcx.JdbcDataSource;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.postgresql.ds.PGSimpleDataSource; import org.postgresql.ds.PGSimpleDataSource;
@ -63,7 +64,7 @@ import static org.assertj.core.api.Assertions.assertThatNoException;
*/ */
class DataSourceBuilderTests { class DataSourceBuilderTests {
private DataSource dataSource; private @Nullable DataSource dataSource;
@AfterEach @AfterEach
void shutdownDataSource() throws IOException { void shutdownDataSource() throws IOException {
@ -621,33 +622,33 @@ class DataSourceBuilderTests {
static class CustomTomcatDataSource extends org.apache.tomcat.jdbc.pool.DataSource { static class CustomTomcatDataSource extends org.apache.tomcat.jdbc.pool.DataSource {
private String jdbcUrl; private @Nullable String jdbcUrl;
private String user; private @Nullable String user;
private String driverClass; private @Nullable String driverClass;
String getJdbcUrl() { @Nullable String getJdbcUrl() {
return this.jdbcUrl; return this.jdbcUrl;
} }
void setJdbcUrl(String jdbcUrl) { void setJdbcUrl(@Nullable String jdbcUrl) {
this.jdbcUrl = jdbcUrl; this.jdbcUrl = jdbcUrl;
} }
String getUser() { @Nullable String getUser() {
return this.user; return this.user;
} }
void setUser(String user) { void setUser(@Nullable String user) {
this.user = user; this.user = user;
} }
String getDriverClass() { @Nullable String getDriverClass() {
return this.driverClass; return this.driverClass;
} }
void setDriverClass(String driverClass) { void setDriverClass(@Nullable String driverClass) {
this.driverClass = driverClass; this.driverClass = driverClass;
} }
@ -655,9 +656,9 @@ class DataSourceBuilderTests {
static class LimitedCustomDataSource extends AbstractDataSource { static class LimitedCustomDataSource extends AbstractDataSource {
private String username; private @Nullable String username;
private String password; private @Nullable String password;
@Override @Override
public Connection getConnection() throws SQLException { public Connection getConnection() throws SQLException {
@ -669,19 +670,19 @@ class DataSourceBuilderTests {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
String getUsername() { @Nullable String getUsername() {
return this.username; return this.username;
} }
void setUsername(String username) { void setUsername(@Nullable String username) {
this.username = username; this.username = username;
} }
String getPassword() { @Nullable String getPassword() {
return this.password; return this.password;
} }
void setPassword(String password) { void setPassword(@Nullable String password) {
this.password = password; this.password = password;
} }
@ -689,13 +690,13 @@ class DataSourceBuilderTests {
static class NoDriverClassNameDataSource extends LimitedCustomDataSource { static class NoDriverClassNameDataSource extends LimitedCustomDataSource {
private String url; private @Nullable String url;
String getUrl() { @Nullable String getUrl() {
return this.url; return this.url;
} }
void setUrl(String url) { void setUrl(@Nullable String url) {
this.url = url; this.url = url;
} }
@ -703,23 +704,23 @@ class DataSourceBuilderTests {
static class CustomDataSource extends LimitedCustomDataSource { static class CustomDataSource extends LimitedCustomDataSource {
private String driverClassName; private @Nullable String driverClassName;
private String url; private @Nullable String url;
String getDriverClassName() { @Nullable String getDriverClassName() {
return this.driverClassName; return this.driverClassName;
} }
void setDriverClassName(String driverClassName) { void setDriverClassName(@Nullable String driverClassName) {
this.driverClassName = driverClassName; this.driverClassName = driverClassName;
} }
String getUrl() { @Nullable String getUrl() {
return this.url; return this.url;
} }
void setUrl(String url) { void setUrl(@Nullable String url) {
this.url = url; this.url = url;
} }

View File

@ -29,6 +29,7 @@ import java.util.stream.Stream;
import javax.sql.XADataSource; import javax.sql.XADataSource;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
@ -71,19 +72,20 @@ class DatabaseDriverClassNameTests {
} }
static Stream<? extends Arguments> databaseClassIsOfRequiredType() { static Stream<? extends Arguments> databaseClassIsOfRequiredType() {
return Stream.concat(argumentsForType(Driver.class, DatabaseDriver::getDriverClassName), Function<DatabaseDriver, @Nullable String> getDriverClassName = DatabaseDriver::getDriverClassName;
return Stream.concat(argumentsForType(Driver.class, getDriverClassName),
argumentsForType(XADataSource.class, argumentsForType(XADataSource.class,
(databaseDriver) -> databaseDriver.getXaDataSourceClassName() != null, (databaseDriver) -> databaseDriver.getXaDataSourceClassName() != null,
DatabaseDriver::getXaDataSourceClassName)); DatabaseDriver::getXaDataSourceClassName));
} }
private static Stream<? extends Arguments> argumentsForType(Class<?> type, private static Stream<? extends Arguments> argumentsForType(Class<?> type,
Function<DatabaseDriver, String> classNameExtractor) { Function<DatabaseDriver, @Nullable String> classNameExtractor) {
return argumentsForType(type, (databaseDriver) -> true, classNameExtractor); return argumentsForType(type, (databaseDriver) -> true, classNameExtractor);
} }
private static Stream<? extends Arguments> argumentsForType(Class<?> type, Predicate<DatabaseDriver> predicate, private static Stream<? extends Arguments> argumentsForType(Class<?> type, Predicate<DatabaseDriver> predicate,
Function<DatabaseDriver, String> classNameExtractor) { Function<DatabaseDriver, @Nullable String> classNameExtractor) {
return Stream.of(DatabaseDriver.values()) return Stream.of(DatabaseDriver.values())
.filter((databaseDriver) -> !EXCLUDED_DRIVERS.contains(databaseDriver)) .filter((databaseDriver) -> !EXCLUDED_DRIVERS.contains(databaseDriver))
.filter(predicate) .filter(predicate)

View File

@ -22,6 +22,7 @@ import java.sql.SQLException;
import javax.sql.DataSource; import javax.sql.DataSource;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
@ -61,6 +62,7 @@ class EmbeddedDatabaseConnectionTests {
} }
@Test @Test
@SuppressWarnings("NullAway") // Test null check
void getUrlWithNullDatabaseNameForHsqldb() { void getUrlWithNullDatabaseNameForHsqldb() {
assertThatIllegalArgumentException().isThrownBy(() -> EmbeddedDatabaseConnection.HSQLDB.getUrl(null)) assertThatIllegalArgumentException().isThrownBy(() -> EmbeddedDatabaseConnection.HSQLDB.getUrl(null))
.withMessageContaining("'databaseName' must not be empty"); .withMessageContaining("'databaseName' must not be empty");
@ -142,7 +144,7 @@ class EmbeddedDatabaseConnectionTests {
.isEmbedded(mockDataSource(EmbeddedDatabaseConnection.H2.getDriverClassName(), null))).isTrue(); .isEmbedded(mockDataSource(EmbeddedDatabaseConnection.H2.getDriverClassName(), null))).isTrue();
} }
DataSource mockDataSource(String productName, String connectionUrl) throws SQLException { DataSource mockDataSource(@Nullable String productName, @Nullable String connectionUrl) throws SQLException {
DatabaseMetaData metaData = mock(DatabaseMetaData.class); DatabaseMetaData metaData = mock(DatabaseMetaData.class);
given(metaData.getDatabaseProductName()).willReturn(productName); given(metaData.getDatabaseProductName()).willReturn(productName);
given(metaData.getURL()).willReturn(connectionUrl); given(metaData.getURL()).willReturn(connectionUrl);

View File

@ -37,6 +37,7 @@ import io.r2dbc.spi.ConnectionFactory;
import oracle.ucp.jdbc.PoolDataSourceImpl; import oracle.ucp.jdbc.PoolDataSourceImpl;
import org.apache.commons.dbcp2.BasicDataSource; import org.apache.commons.dbcp2.BasicDataSource;
import org.assertj.core.api.InstanceOfAssertFactories; import org.assertj.core.api.InstanceOfAssertFactories;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.BeanCreationException;
@ -292,8 +293,9 @@ class DataSourceAutoConfigurationTests {
TestDataSource source = (TestDataSource) dataSource; TestDataSource source = (TestDataSource) dataSource;
assertThat(source.getUsername()).isEqualTo("user-1"); assertThat(source.getUsername()).isEqualTo("user-1");
assertThat(source.getPassword()).isEqualTo("password-1"); assertThat(source.getPassword()).isEqualTo("password-1");
assertThat(source.getDriver().getClass().getName()) Driver driver = source.getDriver();
.isEqualTo(DatabaseDriver.POSTGRESQL.getDriverClassName()); assertThat(driver).isNotNull();
assertThat(driver.getClass().getName()).isEqualTo(DatabaseDriver.POSTGRESQL.getDriverClassName());
assertThat(source.getUrl()).isEqualTo("jdbc:customdb://customdb.example.com:12345/database-1"); assertThat(source.getUrl()).isEqualTo("jdbc:customdb://customdb.example.com:12345/database-1");
}); });
} }
@ -326,7 +328,7 @@ class DataSourceAutoConfigurationTests {
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
static class TestDataSourceConfiguration { static class TestDataSourceConfiguration {
private BasicDataSource pool; private @Nullable BasicDataSource pool;
@Bean @Bean
DataSource dataSource() { DataSource dataSource() {

View File

@ -16,6 +16,7 @@
package org.springframework.boot.jdbc.autoconfigure; package org.springframework.boot.jdbc.autoconfigure;
import com.mchange.util.AssertException;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.BeanCreationException;
@ -62,7 +63,9 @@ class DataSourceBeanCreationFailureAnalyzerTests {
assertThat(failure).isNotNull(); assertThat(failure).isNotNull();
DataSourceBeanCreationFailureAnalyzer failureAnalyzer = new DataSourceBeanCreationFailureAnalyzer( DataSourceBeanCreationFailureAnalyzer failureAnalyzer = new DataSourceBeanCreationFailureAnalyzer(
this.environment); this.environment);
return failureAnalyzer.analyze(failure); FailureAnalysis analysis = failureAnalyzer.analyze(failure);
assertThat(analysis).isNotNull();
return analysis;
} }
private BeanCreationException createFailure(Class<?> configuration) { private BeanCreationException createFailure(Class<?> configuration) {
@ -72,7 +75,7 @@ class DataSourceBeanCreationFailureAnalyzerTests {
context.register(configuration); context.register(configuration);
context.refresh(); context.refresh();
context.close(); context.close();
return null; throw new AssertException("Shouldn't be reached!");
} }
catch (BeanCreationException ex) { catch (BeanCreationException ex) {
return ex; return ex;

View File

@ -122,7 +122,8 @@ class DataSourceInitializationAutoConfigurationTests {
@Bean @Bean
DataSourceScriptDatabaseInitializer customInitializer() { DataSourceScriptDatabaseInitializer customInitializer() {
return new DataSourceScriptDatabaseInitializer(null, new DatabaseInitializationSettings()) { return new DataSourceScriptDatabaseInitializer(mock(DataSource.class),
new DatabaseInitializationSettings()) {
@Override @Override
protected void runScripts(Scripts scripts) { protected void runScripts(Scripts scripts) {

View File

@ -19,9 +19,11 @@ package org.springframework.boot.jdbc.autoconfigure;
import org.apache.commons.dbcp2.BasicDataSource; import org.apache.commons.dbcp2.BasicDataSource;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.jdbc.DatabaseDriver; import org.springframework.boot.jdbc.DatabaseDriver;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
/** /**
* Tests for {@link Dbcp2JdbcConnectionDetailsBeanPostProcessor}. * Tests for {@link Dbcp2JdbcConnectionDetailsBeanPostProcessor}.
@ -33,13 +35,14 @@ import static org.assertj.core.api.Assertions.assertThat;
class Dbcp2JdbcConnectionDetailsBeanPostProcessorTests { class Dbcp2JdbcConnectionDetailsBeanPostProcessorTests {
@Test @Test
@SuppressWarnings("unchecked")
void setUsernamePasswordUrlAndDriverClassName() { void setUsernamePasswordUrlAndDriverClassName() {
BasicDataSource dataSource = new BasicDataSource(); BasicDataSource dataSource = new BasicDataSource();
dataSource.setUrl("will-be-overwritten"); dataSource.setUrl("will-be-overwritten");
dataSource.setUsername("will-be-overwritten"); dataSource.setUsername("will-be-overwritten");
dataSource.setPassword("will-be-overwritten"); dataSource.setPassword("will-be-overwritten");
dataSource.setDriverClassName("will-be-overwritten"); dataSource.setDriverClassName("will-be-overwritten");
new Dbcp2JdbcConnectionDetailsBeanPostProcessor(null).processDataSource(dataSource, new Dbcp2JdbcConnectionDetailsBeanPostProcessor(mock(ObjectProvider.class)).processDataSource(dataSource,
new TestJdbcConnectionDetails()); new TestJdbcConnectionDetails());
assertThat(dataSource.getUrl()).isEqualTo("jdbc:customdb://customdb.example.com:12345/database-1"); assertThat(dataSource.getUrl()).isEqualTo("jdbc:customdb://customdb.example.com:12345/database-1");
assertThat(dataSource.getUserName()).isEqualTo("user-1"); assertThat(dataSource.getUserName()).isEqualTo("user-1");

View File

@ -22,6 +22,7 @@ import java.sql.SQLException;
import javax.sql.DataSource; import javax.sql.DataSource;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -38,7 +39,7 @@ import static org.assertj.core.api.Assertions.assertThat;
*/ */
class EmbeddedDataSourceConfigurationTests { class EmbeddedDataSourceConfigurationTests {
private AnnotationConfigApplicationContext context; private @Nullable AnnotationConfigApplicationContext context;
@AfterEach @AfterEach
void closeContext() { void closeContext() {

View File

@ -26,6 +26,7 @@ import javax.sql.DataSource;
import com.zaxxer.hikari.HikariDataSource; import com.zaxxer.hikari.HikariDataSource;
import org.assertj.core.api.InstanceOfAssertFactories; import org.assertj.core.api.InstanceOfAssertFactories;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
@ -239,12 +240,12 @@ class HikariDataSourceConfigurationTests {
public static class MockDataSource implements DataSource { public static class MockDataSource implements DataSource {
@Override @Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException { public @Nullable Logger getParentLogger() throws SQLFeatureNotSupportedException {
return null; return null;
} }
@Override @Override
public <T> T unwrap(Class<T> iface) throws SQLException { public <T> @Nullable T unwrap(Class<T> iface) throws SQLException {
return null; return null;
} }
@ -264,7 +265,7 @@ class HikariDataSourceConfigurationTests {
} }
@Override @Override
public PrintWriter getLogWriter() throws SQLException { public @Nullable PrintWriter getLogWriter() throws SQLException {
return null; return null;
} }

View File

@ -16,7 +16,9 @@
package org.springframework.boot.jdbc.autoconfigure; package org.springframework.boot.jdbc.autoconfigure;
import com.mchange.util.AssertException;
import com.zaxxer.hikari.HikariDataSource; import com.zaxxer.hikari.HikariDataSource;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.BeanCreationException;
@ -53,7 +55,7 @@ class HikariDriverConfigurationFailureAnalyzerTests {
assertThat(failureAnalysis).isNull(); assertThat(failureAnalysis).isNull();
} }
private FailureAnalysis performAnalysis(Class<?> configuration) { private @Nullable FailureAnalysis performAnalysis(Class<?> configuration) {
BeanCreationException failure = createFailure(configuration); BeanCreationException failure = createFailure(configuration);
assertThat(failure).isNotNull(); assertThat(failure).isNotNull();
return new HikariDriverConfigurationFailureAnalyzer().analyze(failure); return new HikariDriverConfigurationFailureAnalyzer().analyze(failure);
@ -69,7 +71,7 @@ class HikariDriverConfigurationFailureAnalyzerTests {
try { try {
context.refresh(); context.refresh();
context.close(); context.close();
return null; throw new AssertException("Shouldn't be reached!");
} }
catch (BeanCreationException ex) { catch (BeanCreationException ex) {
return ex; return ex;

View File

@ -19,6 +19,7 @@ package org.springframework.boot.jdbc.autoconfigure;
import com.zaxxer.hikari.HikariDataSource; import com.zaxxer.hikari.HikariDataSource;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.jdbc.DatabaseDriver; import org.springframework.boot.jdbc.DatabaseDriver;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -34,13 +35,14 @@ import static org.mockito.Mockito.mock;
class HikariJdbcConnectionDetailsBeanPostProcessorTests { class HikariJdbcConnectionDetailsBeanPostProcessorTests {
@Test @Test
@SuppressWarnings("unchecked")
void setUsernamePasswordAndUrl() { void setUsernamePasswordAndUrl() {
HikariDataSource dataSource = new HikariDataSource(); HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl("will-be-overwritten"); dataSource.setJdbcUrl("will-be-overwritten");
dataSource.setUsername("will-be-overwritten"); dataSource.setUsername("will-be-overwritten");
dataSource.setPassword("will-be-overwritten"); dataSource.setPassword("will-be-overwritten");
dataSource.setDriverClassName(DatabaseDriver.H2.getDriverClassName()); dataSource.setDriverClassName(DatabaseDriver.H2.getDriverClassName());
new HikariJdbcConnectionDetailsBeanPostProcessor(null).processDataSource(dataSource, new HikariJdbcConnectionDetailsBeanPostProcessor(mock(ObjectProvider.class)).processDataSource(dataSource,
new TestJdbcConnectionDetails()); new TestJdbcConnectionDetails());
assertThat(dataSource.getJdbcUrl()).isEqualTo("jdbc:customdb://customdb.example.com:12345/database-1"); assertThat(dataSource.getJdbcUrl()).isEqualTo("jdbc:customdb://customdb.example.com:12345/database-1");
assertThat(dataSource.getUsername()).isEqualTo("user-1"); assertThat(dataSource.getUsername()).isEqualTo("user-1");
@ -49,11 +51,13 @@ class HikariJdbcConnectionDetailsBeanPostProcessorTests {
} }
@Test @Test
@SuppressWarnings("unchecked")
void toleratesConnectionDetailsWithNullDriverClassName() { void toleratesConnectionDetailsWithNullDriverClassName() {
HikariDataSource dataSource = new HikariDataSource(); HikariDataSource dataSource = new HikariDataSource();
dataSource.setDriverClassName(DatabaseDriver.H2.getDriverClassName()); dataSource.setDriverClassName(DatabaseDriver.H2.getDriverClassName());
JdbcConnectionDetails connectionDetails = mock(JdbcConnectionDetails.class); JdbcConnectionDetails connectionDetails = mock(JdbcConnectionDetails.class);
new HikariJdbcConnectionDetailsBeanPostProcessor(null).processDataSource(dataSource, connectionDetails); new HikariJdbcConnectionDetailsBeanPostProcessor(mock(ObjectProvider.class)).processDataSource(dataSource,
connectionDetails);
assertThat(dataSource.getDriverClassName()).isEqualTo(DatabaseDriver.H2.getDriverClassName()); assertThat(dataSource.getDriverClassName()).isEqualTo(DatabaseDriver.H2.getDriverClassName());
} }

View File

@ -23,6 +23,7 @@ import java.lang.annotation.Target;
import javax.sql.DataSource; import javax.sql.DataSource;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
@ -262,7 +263,7 @@ class JdbcTemplateAutoConfigurationTests {
static class DataSourceInitializationValidator { static class DataSourceInitializationValidator {
private final Integer count; private final @Nullable Integer count;
DataSourceInitializationValidator(JdbcTemplate jdbcTemplate) { DataSourceInitializationValidator(JdbcTemplate jdbcTemplate) {
this.count = jdbcTemplate.queryForObject("SELECT COUNT(*) from BAR", Integer.class); this.count = jdbcTemplate.queryForObject("SELECT COUNT(*) from BAR", Integer.class);

View File

@ -22,6 +22,7 @@ import javax.naming.Context;
import javax.sql.DataSource; import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSource; import org.apache.commons.dbcp2.BasicDataSource;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -49,7 +50,7 @@ class JndiDataSourceAutoConfigurationTests {
private String initialContextFactory; private String initialContextFactory;
private AnnotationConfigApplicationContext context; private @Nullable AnnotationConfigApplicationContext context;
@BeforeEach @BeforeEach
void setupJndi() { void setupJndi() {

View File

@ -22,9 +22,11 @@ import oracle.ucp.jdbc.PoolDataSourceImpl;
import oracle.ucp.util.OpaqueString; import oracle.ucp.util.OpaqueString;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.jdbc.DatabaseDriver; import org.springframework.boot.jdbc.DatabaseDriver;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
/** /**
* Tests for {@link OracleUcpJdbcConnectionDetailsBeanPostProcessor}. * Tests for {@link OracleUcpJdbcConnectionDetailsBeanPostProcessor}.
@ -36,13 +38,14 @@ import static org.assertj.core.api.Assertions.assertThat;
class OracleUcpJdbcConnectionDetailsBeanPostProcessorTests { class OracleUcpJdbcConnectionDetailsBeanPostProcessorTests {
@Test @Test
@SuppressWarnings("unchecked")
void setUsernamePasswordUrlAndDriverClassName() throws SQLException { void setUsernamePasswordUrlAndDriverClassName() throws SQLException {
PoolDataSourceImpl dataSource = new PoolDataSourceImpl(); PoolDataSourceImpl dataSource = new PoolDataSourceImpl();
dataSource.setURL("will-be-overwritten"); dataSource.setURL("will-be-overwritten");
dataSource.setUser("will-be-overwritten"); dataSource.setUser("will-be-overwritten");
dataSource.setPassword("will-be-overwritten"); dataSource.setPassword("will-be-overwritten");
dataSource.setConnectionFactoryClassName("will-be-overwritten"); dataSource.setConnectionFactoryClassName("will-be-overwritten");
new OracleUcpJdbcConnectionDetailsBeanPostProcessor(null).processDataSource(dataSource, new OracleUcpJdbcConnectionDetailsBeanPostProcessor(mock(ObjectProvider.class)).processDataSource(dataSource,
new TestJdbcConnectionDetails()); new TestJdbcConnectionDetails());
assertThat(dataSource.getURL()).isEqualTo("jdbc:customdb://customdb.example.com:12345/database-1"); assertThat(dataSource.getURL()).isEqualTo("jdbc:customdb://customdb.example.com:12345/database-1");
assertThat(dataSource.getUser()).isEqualTo("user-1"); assertThat(dataSource.getUser()).isEqualTo("user-1");

View File

@ -18,6 +18,8 @@ package org.springframework.boot.jdbc.autoconfigure;
import org.springframework.boot.jdbc.DatabaseDriver; import org.springframework.boot.jdbc.DatabaseDriver;
import static org.assertj.core.api.Assertions.assertThat;
/** /**
* {@link JdbcConnectionDetails} used in tests. * {@link JdbcConnectionDetails} used in tests.
* *
@ -42,12 +44,16 @@ class TestJdbcConnectionDetails implements JdbcConnectionDetails {
@Override @Override
public String getDriverClassName() { public String getDriverClassName() {
return DatabaseDriver.POSTGRESQL.getDriverClassName(); String driverClassName = DatabaseDriver.POSTGRESQL.getDriverClassName();
assertThat(driverClassName).isNotNull();
return driverClassName;
} }
@Override @Override
public String getXaDataSourceClassName() { public String getXaDataSourceClassName() {
return DatabaseDriver.POSTGRESQL.getXaDataSourceClassName(); String xaDataSourceClassName = DatabaseDriver.POSTGRESQL.getXaDataSourceClassName();
assertThat(xaDataSourceClassName).isNotNull();
return xaDataSourceClassName;
} }
} }

View File

@ -19,9 +19,11 @@ package org.springframework.boot.jdbc.autoconfigure;
import org.apache.tomcat.jdbc.pool.DataSource; import org.apache.tomcat.jdbc.pool.DataSource;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.jdbc.DatabaseDriver; import org.springframework.boot.jdbc.DatabaseDriver;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
/** /**
* Tests for {@link TomcatJdbcConnectionDetailsBeanPostProcessor}. * Tests for {@link TomcatJdbcConnectionDetailsBeanPostProcessor}.
@ -33,13 +35,14 @@ import static org.assertj.core.api.Assertions.assertThat;
class TomcatJdbcConnectionDetailsBeanPostProcessorTests { class TomcatJdbcConnectionDetailsBeanPostProcessorTests {
@Test @Test
@SuppressWarnings("unchecked")
void setUsernamePasswordUrlAndDriverClassName() { void setUsernamePasswordUrlAndDriverClassName() {
DataSource dataSource = new DataSource(); DataSource dataSource = new DataSource();
dataSource.setUrl("will-be-overwritten"); dataSource.setUrl("will-be-overwritten");
dataSource.setUsername("will-be-overwritten"); dataSource.setUsername("will-be-overwritten");
dataSource.setPassword("will-be-overwritten"); dataSource.setPassword("will-be-overwritten");
dataSource.setDriverClassName("will-be-overwritten"); dataSource.setDriverClassName("will-be-overwritten");
new TomcatJdbcConnectionDetailsBeanPostProcessor(null).processDataSource(dataSource, new TomcatJdbcConnectionDetailsBeanPostProcessor(mock(ObjectProvider.class)).processDataSource(dataSource,
new TestJdbcConnectionDetails()); new TestJdbcConnectionDetails());
assertThat(dataSource.getUrl()).isEqualTo("jdbc:customdb://customdb.example.com:12345/database-1"); assertThat(dataSource.getUrl()).isEqualTo("jdbc:customdb://customdb.example.com:12345/database-1");
assertThat(dataSource.getUsername()).isEqualTo("user-1"); assertThat(dataSource.getUsername()).isEqualTo("user-1");

View File

@ -21,6 +21,7 @@ import javax.sql.XADataSource;
import com.ibm.db2.jcc.DB2XADataSource; import com.ibm.db2.jcc.DB2XADataSource;
import org.hsqldb.jdbc.pool.JDBCXADataSource; import org.hsqldb.jdbc.pool.JDBCXADataSource;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.postgresql.xa.PGXADataSource; import org.postgresql.xa.PGXADataSource;
@ -161,7 +162,7 @@ class XADataSourceAutoConfigurationTests {
static class MockXADataSourceWrapper implements XADataSourceWrapper { static class MockXADataSourceWrapper implements XADataSourceWrapper {
private XADataSource dataSource; private @Nullable XADataSource dataSource;
@Override @Override
public DataSource wrapDataSource(XADataSource dataSource) { public DataSource wrapDataSource(XADataSource dataSource) {
@ -169,7 +170,7 @@ class XADataSourceAutoConfigurationTests {
return mock(DataSource.class); return mock(DataSource.class);
} }
XADataSource getXaDataSource() { @Nullable XADataSource getXaDataSource() {
return this.dataSource; return this.dataSource;
} }

View File

@ -38,9 +38,10 @@ import static org.mockito.Mockito.mock;
*/ */
class JdbcUrlBuilderTests { class JdbcUrlBuilderTests {
private JdbcUrlBuilder builder = new JdbcUrlBuilder("mydb", 1234); private final JdbcUrlBuilder builder = new JdbcUrlBuilder("mydb", 1234);
@Test @Test
@SuppressWarnings("NullAway") // Test null check
void createWhenDriverProtocolIsNullThrowsException() { void createWhenDriverProtocolIsNullThrowsException() {
assertThatIllegalArgumentException().isThrownBy(() -> new JdbcUrlBuilder(null, 123)) assertThatIllegalArgumentException().isThrownBy(() -> new JdbcUrlBuilder(null, 123))
.withMessage("'driverProtocol' must not be null"); .withMessage("'driverProtocol' must not be null");
@ -82,6 +83,7 @@ class JdbcUrlBuilderTests {
} }
@Test @Test
@SuppressWarnings("NullAway") // Test null check
void buildWhenServiceIsNullThrowsException() { void buildWhenServiceIsNullThrowsException() {
assertThatIllegalArgumentException().isThrownBy(() -> this.builder.build(null, "mydb")) assertThatIllegalArgumentException().isThrownBy(() -> this.builder.build(null, "mydb"))
.withMessage("'service' must not be null"); .withMessage("'service' must not be null");

View File

@ -54,7 +54,9 @@ class DataSourceHealthIndicatorTests {
void init() { void init() {
EmbeddedDatabaseConnection db = EmbeddedDatabaseConnection.HSQLDB; EmbeddedDatabaseConnection db = EmbeddedDatabaseConnection.HSQLDB;
this.dataSource = new SingleConnectionDataSource(db.getUrl("testdb") + ";shutdown=true", "sa", "", false); this.dataSource = new SingleConnectionDataSource(db.getUrl("testdb") + ";shutdown=true", "sa", "", false);
this.dataSource.setDriverClassName(db.getDriverClassName()); String driverClassName = db.getDriverClassName();
assertThat(driverClassName).isNotNull();
this.dataSource.setDriverClassName(driverClassName);
} }
@AfterEach @AfterEach

View File

@ -109,7 +109,9 @@ class DataSourceScriptDatabaseInitializerTests
} }
private int numberOfRows(DataSource dataSource, String sql) { private int numberOfRows(DataSource dataSource, String sql) {
return new JdbcTemplate(dataSource).queryForObject(sql, Integer.class); Integer rows = new JdbcTemplate(dataSource).queryForObject(sql, Integer.class);
assertThat(rows).isNotNull();
return rows;
} }
@Override @Override

View File

@ -54,7 +54,7 @@ abstract class AbstractDataSourcePoolMetadataTests<D extends AbstractDataSourceP
void getPoolSizeNoConnection() { void getPoolSizeNoConnection() {
// Make sure the pool is initialized // Make sure the pool is initialized
JdbcTemplate jdbcTemplate = new JdbcTemplate(getDataSourceMetadata().getDataSource()); JdbcTemplate jdbcTemplate = new JdbcTemplate(getDataSourceMetadata().getDataSource());
jdbcTemplate.execute((ConnectionCallback<Void>) (connection) -> null); jdbcTemplate.execute((ConnectionCallback<Object>) (connection) -> new Object());
assertThat(getDataSourceMetadata().getActive()).isZero(); assertThat(getDataSourceMetadata().getActive()).isZero();
assertThat(getDataSourceMetadata().getUsage()).isZero(); assertThat(getDataSourceMetadata().getUsage()).isZero();
} }
@ -62,30 +62,30 @@ abstract class AbstractDataSourcePoolMetadataTests<D extends AbstractDataSourceP
@Test @Test
void getPoolSizeOneConnection() { void getPoolSizeOneConnection() {
JdbcTemplate jdbcTemplate = new JdbcTemplate(getDataSourceMetadata().getDataSource()); JdbcTemplate jdbcTemplate = new JdbcTemplate(getDataSourceMetadata().getDataSource());
jdbcTemplate.execute((ConnectionCallback<Void>) (connection) -> { jdbcTemplate.execute((ConnectionCallback<Object>) (connection) -> {
assertThat(getDataSourceMetadata().getActive()).isOne(); assertThat(getDataSourceMetadata().getActive()).isOne();
assertThat(getDataSourceMetadata().getUsage()).isEqualTo(0.5f); assertThat(getDataSourceMetadata().getUsage()).isEqualTo(0.5f);
return null; return new Object();
}); });
} }
@Test @Test
void getIdle() { void getIdle() {
JdbcTemplate jdbcTemplate = new JdbcTemplate(getDataSourceMetadata().getDataSource()); JdbcTemplate jdbcTemplate = new JdbcTemplate(getDataSourceMetadata().getDataSource());
jdbcTemplate.execute((ConnectionCallback<Void>) (connection) -> null); jdbcTemplate.execute((ConnectionCallback<Object>) (connection) -> new Object());
assertThat(getDataSourceMetadata().getIdle()).isOne(); assertThat(getDataSourceMetadata().getIdle()).isOne();
} }
@Test @Test
void getPoolSizeTwoConnections() { void getPoolSizeTwoConnections() {
final JdbcTemplate jdbcTemplate = new JdbcTemplate(getDataSourceMetadata().getDataSource()); final JdbcTemplate jdbcTemplate = new JdbcTemplate(getDataSourceMetadata().getDataSource());
jdbcTemplate.execute((ConnectionCallback<Void>) (connection) -> { jdbcTemplate.execute((ConnectionCallback<Object>) (connection) -> {
jdbcTemplate.execute((ConnectionCallback<Void>) (connection1) -> { jdbcTemplate.execute((ConnectionCallback<Object>) (connection1) -> {
assertThat(getDataSourceMetadata().getActive()).isEqualTo(2); assertThat(getDataSourceMetadata().getActive()).isEqualTo(2);
assertThat(getDataSourceMetadata().getUsage()).isOne(); assertThat(getDataSourceMetadata().getUsage()).isOne();
return null; return new Object();
}); });
return null; return new Object();
}); });
} }

View File

@ -19,6 +19,7 @@ package org.springframework.boot.jdbc.metadata;
import java.time.Duration; import java.time.Duration;
import org.apache.commons.dbcp2.BasicDataSource; import org.apache.commons.dbcp2.BasicDataSource;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -42,7 +43,7 @@ class CommonsDbcp2DataSourcePoolMetadataTests
void getPoolUsageWithNoCurrent() { void getPoolUsageWithNoCurrent() {
CommonsDbcp2DataSourcePoolMetadata dsm = new CommonsDbcp2DataSourcePoolMetadata(createDataSource()) { CommonsDbcp2DataSourcePoolMetadata dsm = new CommonsDbcp2DataSourcePoolMetadata(createDataSource()) {
@Override @Override
public Integer getActive() { public @Nullable Integer getActive() {
return null; return null;
} }
}; };
@ -53,7 +54,7 @@ class CommonsDbcp2DataSourcePoolMetadataTests
void getPoolUsageWithNoMax() { void getPoolUsageWithNoMax() {
CommonsDbcp2DataSourcePoolMetadata dsm = new CommonsDbcp2DataSourcePoolMetadata(createDataSource()) { CommonsDbcp2DataSourcePoolMetadata dsm = new CommonsDbcp2DataSourcePoolMetadata(createDataSource()) {
@Override @Override
public Integer getMax() { public @Nullable Integer getMax() {
return null; return null;
} }
}; };

View File

@ -38,24 +38,31 @@ import static org.mockito.BDDMockito.given;
class CompositeDataSourcePoolMetadataProviderTests { class CompositeDataSourcePoolMetadataProviderTests {
@Mock @Mock
@SuppressWarnings("NullAway.Init")
private DataSourcePoolMetadataProvider firstProvider; private DataSourcePoolMetadataProvider firstProvider;
@Mock @Mock
@SuppressWarnings("NullAway.Init")
private DataSourcePoolMetadata first; private DataSourcePoolMetadata first;
@Mock @Mock
@SuppressWarnings("NullAway.Init")
private DataSource firstDataSource; private DataSource firstDataSource;
@Mock @Mock
@SuppressWarnings("NullAway.Init")
private DataSourcePoolMetadataProvider secondProvider; private DataSourcePoolMetadataProvider secondProvider;
@Mock @Mock
@SuppressWarnings("NullAway.Init")
private DataSourcePoolMetadata second; private DataSourcePoolMetadata second;
@Mock @Mock
@SuppressWarnings("NullAway.Init")
private DataSource secondDataSource; private DataSource secondDataSource;
@Mock @Mock
@SuppressWarnings("NullAway.Init")
private DataSource unknownDataSource; private DataSource unknownDataSource;
@BeforeEach @BeforeEach