Skip to content

Commit

Permalink
Refine datasource tests related to "empty config" and health checks
Browse files Browse the repository at this point in the history
To be completely sure of what we'll change exactly in further changes.

This is only a refactoring and doesn't change existing test expectations
(though it adds some).

"Empty config" actually means "missing JDBC/reactive URL".
Testing what happens when named datasources are not defined at build
time, in particular, is beside the point.

For health checks, it's just that some configurations were not being
tested, and the next commits may affect the behavior.
  • Loading branch information
yrodiere committed Sep 26, 2024
1 parent a05aff4 commit 90a86bd
Show file tree
Hide file tree
Showing 50 changed files with 1,486 additions and 167 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,23 @@
import io.quarkus.test.QuarkusUnitTest;
import io.restassured.RestAssured;

public class DataSourceHealthCheckConfigActiveFalseTest {
public class ConfigActiveFalseDefaultDatasourceHealthCheckTest {

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.withEmptyApplication()
.withConfigurationResource("application-default-datasource.properties")
.overrideConfigKey("quarkus.datasource.health.enabled", "true")
.overrideConfigKey("quarkus.datasource.active", "false")
// this data source is broken, but will be deactivated,
// so the overall check should pass
.overrideConfigKey("quarkus.datasource.brokenDS.db-kind", "h2")
.overrideConfigKey("quarkus.datasource.brokenDS.jdbc.url", "BROKEN")
.overrideConfigKey("quarkus.datasource.brokenDS.active", "false");
.overrideConfigKey("quarkus.datasource.jdbc.url", "BROKEN");

@Test
public void testDataSourceHealthCheckExclusion() {
RestAssured.when().get("/q/health/ready")
.then()
.body("status", CoreMatchers.equalTo("UP"));
.body("status", CoreMatchers.equalTo("UP"))
// If the datasource is inactive, there should not be a health check
.body("checks[0].data.\"<default>\"", CoreMatchers.nullValue());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package io.quarkus.agroal.test;

import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;
import io.restassured.RestAssured;

public class ConfigActiveFalseNamedDatasourceHealthCheckTest {

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.overrideConfigKey("quarkus.datasource.health.enabled", "true")
.overrideConfigKey("quarkus.datasource.users.active", "false")
// We need at least one build-time property for the datasource,
// otherwise it's considered unconfigured at build time...
.overrideConfigKey("quarkus.datasource.users.db-kind", "h2")
// this data source is broken, but will be deactivated,
// so the overall check should pass
.overrideConfigKey("quarkus.datasource.users.jdbc.url", "BROKEN");

@Test
public void testDataSourceHealthCheckExclusion() {
RestAssured.when().get("/q/health/ready")
.then()
.body("status", CoreMatchers.equalTo("UP"))
// If the datasource is inactive, there should not be a health check
.body("checks[0].data.\"users\"", CoreMatchers.nullValue());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package io.quarkus.agroal.test;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

import javax.sql.DataSource;

import jakarta.inject.Inject;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.agroal.api.AgroalDataSource;
import io.quarkus.arc.InjectableInstance;
import io.quarkus.runtime.configuration.ConfigurationException;
import io.quarkus.test.QuarkusUnitTest;

public class ConfigUrlMissingDefaultDatasourceDynamicInjectionTest {

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
// The URL won't be missing if dev services are enabled
.overrideConfigKey("quarkus.devservices.enabled", "false");

@Inject
InjectableInstance<DataSource> dataSource;

@Inject
InjectableInstance<AgroalDataSource> agroalDataSource;

@Test
public void dataSource() {
doTest(dataSource);
}

@Test
public void agroalDataSource() {
doTest(agroalDataSource);
}

private void doTest(InjectableInstance<? extends DataSource> instance) {
// The bean is always available to be injected during static init
// since we don't know whether the datasource will be active at runtime.
// So the bean proxy cannot be null.
var ds = instance.get();
assertThat(ds).isNotNull();
// However, any attempt to use it at runtime will fail.
assertThatThrownBy(() -> ds.getConnection())
.isInstanceOf(ConfigurationException.class)
.hasMessageContainingAll("quarkus.datasource.jdbc.url has not been defined");
;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package io.quarkus.agroal.test;

import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;
import io.restassured.RestAssured;

public class ConfigUrlMissingDefaultDatasourceHealthCheckTest {

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.overrideConfigKey("quarkus.datasource.health.enabled", "true")
// The URL won't be missing if dev services are enabled
.overrideConfigKey("quarkus.devservices.enabled", "false");

@Test
public void testDataSourceHealthCheckExclusion() {
RestAssured.when().get("/q/health/ready")
.then()
// UnconfiguredDataSource always reports as healthy...
// https://github.com/quarkusio/quarkus/issues/36666
.body("status", CoreMatchers.equalTo("UP"))
.body("checks[0].data.\"<default>\"", CoreMatchers.equalTo("UP"));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package io.quarkus.agroal.test;

import static org.assertj.core.api.Assertions.assertThatThrownBy;

import java.sql.SQLException;

import javax.sql.DataSource;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.runtime.configuration.ConfigurationException;
import io.quarkus.test.QuarkusUnitTest;

public class ConfigUrlMissingDefaultDatasourceStaticInjectionTest {

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
// The URL won't be missing if dev services are enabled
.overrideConfigKey("quarkus.devservices.enabled", "false");

@Inject
MyBean myBean;

@Test
public void test() {
assertThatThrownBy(() -> myBean.useDatasource())
.isInstanceOf(ConfigurationException.class)
.hasMessageContainingAll("quarkus.datasource.jdbc.url has not been defined");
}

@ApplicationScoped
public static class MyBean {
@Inject
DataSource ds;

public void useDatasource() throws SQLException {
ds.getConnection();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package io.quarkus.agroal.test;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

import javax.sql.DataSource;

import jakarta.inject.Inject;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.agroal.api.AgroalDataSource;
import io.quarkus.arc.InjectableInstance;
import io.quarkus.runtime.configuration.ConfigurationException;
import io.quarkus.test.QuarkusUnitTest;

public class ConfigUrlMissingNamedDatasourceDynamicInjectionTest {

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
// The URL won't be missing if dev services are enabled
.overrideConfigKey("quarkus.devservices.enabled", "false")
// We need at least one build-time property for the datasource,
// otherwise it's considered unconfigured at build time...
.overrideConfigKey("quarkus.datasource.users.db-kind", "h2");

@Inject
@io.quarkus.agroal.DataSource("users")
InjectableInstance<DataSource> dataSource;

@Inject
@io.quarkus.agroal.DataSource("users")
InjectableInstance<AgroalDataSource> agroalDataSource;

@Test
public void dataSource() {
doTest(dataSource);
}

@Test
public void agroalDataSource() {
doTest(agroalDataSource);
}

private void doTest(InjectableInstance<? extends DataSource> instance) {
// The bean is always available to be injected during static init
// since we don't know whether the datasource will be active at runtime.
// So the bean cannot be null.
var ds = instance.get();
assertThat(ds).isNotNull();
// However, any attempt to use it at runtime will fail.
assertThatThrownBy(() -> ds.getConnection())
.isInstanceOf(ConfigurationException.class)
.hasMessageContainingAll("quarkus.datasource.\"users\".jdbc.url has not been defined");
;
;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package io.quarkus.agroal.test;

import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;
import io.restassured.RestAssured;

public class ConfigUrlMissingNamedDatasourceHealthCheckTest {

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.overrideConfigKey("quarkus.datasource.health.enabled", "true")
// The URL won't be missing if dev services are enabled
.overrideConfigKey("quarkus.devservices.enabled", "false")
// We need at least one build-time property for the datasource,
// otherwise it's considered unconfigured at build time...
.overrideConfigKey("quarkus.datasource.users.db-kind", "h2");

@Test
public void testDataSourceHealthCheckExclusion() {
RestAssured.when().get("/q/health/ready")
.then()
// UnconfiguredDataSource always reports as healthy...
// https://github.com/quarkusio/quarkus/issues/36666
.body("status", CoreMatchers.equalTo("UP"))
.body("checks[0].data.\"users\"", CoreMatchers.equalTo("UP"));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package io.quarkus.agroal.test;

import static org.assertj.core.api.Assertions.assertThatThrownBy;

import java.sql.SQLException;

import javax.sql.DataSource;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.runtime.configuration.ConfigurationException;
import io.quarkus.test.QuarkusUnitTest;

public class ConfigUrlMissingNamedDatasourceStaticInjectionTest {

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
// The URL won't be missing if dev services are enabled
.overrideConfigKey("quarkus.devservices.enabled", "false")
// We need at least one build-time property for the datasource,
// otherwise it's considered unconfigured at build time...
.overrideConfigKey("quarkus.datasource.users.db-kind", "h2");

@Inject
MyBean myBean;

@Test
public void test() {
assertThatThrownBy(() -> myBean.useDatasource())
.isInstanceOf(ConfigurationException.class)
.hasMessageContainingAll("quarkus.datasource.\"users\".jdbc.url has not been defined");
;
}

@ApplicationScoped
public static class MyBean {
@Inject
@io.quarkus.agroal.DataSource("users")
DataSource ds;

public void useDatasource() throws SQLException {
ds.getConnection();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package io.quarkus.flyway.test;

import static org.assertj.core.api.Assertions.assertThatThrownBy;

import jakarta.enterprise.inject.CreationException;
import jakarta.enterprise.inject.Instance;
import jakarta.inject.Inject;

import org.flywaydb.core.Flyway;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;

public class FlywayExtensionConfigUrlMissingDefaultDatasourceDynamicInjectionTest {

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
// The URL won't be missing if dev services are enabled
.overrideConfigKey("quarkus.devservices.enabled", "false");

@Inject
Instance<Flyway> flyway;

@Test
@DisplayName("If the URL is missing for the default datasource, the application should boot, but Flyway should be deactivated for that datasource")
public void testBootSucceedsButFlywayDeactivated() {
assertThatThrownBy(flyway::get)
.isInstanceOf(CreationException.class)
.cause()
.hasMessageContainingAll("Unable to find datasource '<default>' for Flyway",
"Datasource '<default>' is not configured.",
"To solve this, configure datasource '<default>'.",
"Refer to https://quarkus.io/guides/datasource for guidance.");
}

}
Loading

0 comments on commit 90a86bd

Please sign in to comment.