Make Health and Status immutable

Update Health and Status objects to be immutable, update the existing
builder methods to return new instances and add static convenience
methods to Health.
This commit is contained in:
Phillip Webb 2014-05-23 09:46:06 +01:00
parent 660d9e24dc
commit aa03d9a41c
17 changed files with 380 additions and 154 deletions

View File

@ -17,6 +17,7 @@
package org.springframework.boot.actuate.health;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@ -31,21 +32,21 @@ public abstract class AbstractHealthAggregator implements HealthAggregator {
@Override
public final Health aggregate(Map<String, Health> healths) {
Health health = new Health();
List<Status> status = new ArrayList<Status>();
List<Status> statusCandidates = new ArrayList<Status>();
Map<String, Object> details = new LinkedHashMap<String, Object>();
for (Map.Entry<String, Health> entry : healths.entrySet()) {
health.withDetail(entry.getKey(), entry.getValue());
status.add(entry.getValue().getStatus());
details.put(entry.getKey(), entry.getValue());
statusCandidates.add(entry.getValue().getStatus());
}
health.status(aggregateStatus(status));
return health;
return new Health(aggregateStatus(statusCandidates), details);
}
/**
* Actual aggregation logic.
* @param status list of given {@link Status} instances to aggregate
* @return aggregated {@link Status}
* Return the single 'aggregate' status that should be used from the specified
* candidates.
* @param candidates
* @return a single status
*/
protected abstract Status aggregateStatus(List<Status> status);
protected abstract Status aggregateStatus(List<Status> candidates);
}

View File

@ -21,7 +21,7 @@ package org.springframework.boot.actuate.health;
* {@link Health} instance and error handling.
* <p>
* This implementation is only suitable if an {@link Exception} raised from
* {@link #doHealthCheck(Health)} should create a {@link Status#DOWN} health status.
* {@link #doHealthCheck()} should create a {@link Status#DOWN} health status.
*
* @author Christian Dupuis
* @since 1.1.0
@ -30,21 +30,19 @@ public abstract class AbstractHealthIndicator implements HealthIndicator {
@Override
public final Health health() {
Health health = new Health();
try {
doHealthCheck(health);
return doHealthCheck();
}
catch (Exception ex) {
health.down().withException(ex);
return Health.down(ex);
}
return health;
}
/**
* Actual health check logic.
* @param health {@link Health} instance of report status.
* @return the {@link Health}
* @throws Exception any {@link Exception} that should create a {@link Status#DOWN}
* system status.
*/
protected abstract void doHealthCheck(Health health) throws Exception;
protected abstract Health doHealthCheck() throws Exception;
}

View File

@ -16,11 +16,11 @@
package org.springframework.boot.actuate.health;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
@ -29,8 +29,7 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonUnwrapped;
/**
* Value object used to carry information about the health information of a component or
* subsystem.
* Carries information about the health of a component or subsystem.
* <p>
* {@link Health} contains a {@link Status} to express the state of a component or
* subsystem and some additional details to carry some contextual information.
@ -39,68 +38,52 @@ import com.fasterxml.jackson.annotation.JsonUnwrapped;
* in a {@link HealthIndicator} would be:
*
* <pre class="code">
* Health health = new Health();
* try {
* // do some test to determine state of component
* health.up().withDetail(&quot;version&quot;, &quot;1.1.2&quot;);
* return Health.up(&quot;version&quot;, &quot;1.1.2&quot;);
* }
* catch (Exception ex) {
* health.down().withException(ex);
* return Health.down(ex);
* }
* return health;
* </pre>
*
* @author Christian Dupuis
* @author Phillip Webb
* @since 1.1.0
*/
@JsonInclude(Include.NON_EMPTY)
public class Health {
public final class Health {
private Status status;
private static final Map<String, Object> NO_DETAILS = Collections
.<String, Object> emptyMap();
private Map<String, Object> details;
private final Status status;
public Health() {
this(Status.UNKNOWN);
}
private final Map<String, Object> details;
public Health(Status status) {
this.status = status;
this.details = new LinkedHashMap<String, Object>();
}
public Health status(Status status) {
/**
* Create a new {@link Health} instance with the specified status and details.
* @param status the status
* @param details the details or {@code null}
*/
public Health(Status status, Map<String, ?> details) {
Assert.notNull(status, "Status must not be null");
this.status = status;
return this;
}
public Health up() {
return status(Status.UP);
}
public Health down() {
return status(Status.DOWN);
}
public Health withException(Exception ex) {
Assert.notNull(ex, "Exception must not be null");
return withDetail("error", ex.getClass().getName() + ": " + ex.getMessage());
}
@JsonAnySetter
public Health withDetail(String key, Object data) {
Assert.notNull(key, "Key must not be null");
Assert.notNull(data, "Data must not be null");
this.details.put(key, data);
return this;
this.details = Collections.unmodifiableMap(details == null ? NO_DETAILS
: new LinkedHashMap<String, Object>(details));
}
/**
* @return the status of the health (never {@code null})
*/
@JsonUnwrapped
public Status getStatus() {
return this.status;
}
/**
* @return the details of the health or an empty map.
*/
@JsonAnyGetter
public Map<String, Object> getDetails() {
return this.details;
@ -112,19 +95,105 @@ public class Health {
return true;
}
if (obj != null && obj instanceof Health) {
return ObjectUtils.nullSafeEquals(this.status, ((Health) obj).status)
&& ObjectUtils.nullSafeEquals(this.details, ((Health) obj).details);
Health other = (Health) obj;
return this.status.equals(other.status) && this.details.equals(other.details);
}
return false;
}
@Override
public int hashCode() {
int hashCode = 0;
if (this.status != null) {
hashCode = this.status.hashCode();
}
int hashCode = this.status.hashCode();
return 13 * hashCode + this.details.hashCode();
}
@Override
public String toString() {
return getStatus() + " " + getDetails();
}
/**
* Create a new {@link Health} object from this one, containing an additional
* exception detail.
* @param ex the exception
* @return a new {@link Health} instance
*/
public Health withException(Exception ex) {
Assert.notNull(ex, "Exception must not be null");
return withDetail("error", ex.getClass().getName() + ": " + ex.getMessage());
}
/**
* Create a new {@link Health} object from this one, containing an additional detail.
* @param key the detail key
* @param data the detail data
* @return a new {@link Health} instance
*/
@JsonAnySetter
public Health withDetail(String key, Object data) {
Assert.notNull(key, "Key must not be null");
Assert.notNull(data, "Data must not be null");
Map<String, Object> details = new LinkedHashMap<String, Object>(this.details);
details.put(key, data);
return new Health(this.status, details);
}
/**
* Create a new {@link Health} instance with an {@link Status#UNKNOWN} status.
* @return a new {@link Health} instance
*/
public static Health unknown() {
return status(Status.UNKNOWN);
}
/**
* Create a new {@link Health} instance with an {@link Status#UP} status.
* @return a new {@link Health} instance
*/
public static Health up() {
return status(Status.UP);
}
/**
* Create a new {@link Health} instance with an {@link Status#DOWN} status an the
* specified exception details.
* @param ex the exception
* @return a new {@link Health} instance
*/
public static Health down(Exception ex) {
return down().withException(ex);
}
/**
* Create a new {@link Health} instance with a {@link Status#DOWN} status.
* @return a new {@link Health} instance
*/
public static Health down() {
return status(Status.DOWN);
}
/**
* Create a new {@link Health} instance with an {@link Status#OUT_OF_SERVICE} status.
* @return a new {@link Health} instance
*/
public static Health outOfService() {
return status(Status.OUT_OF_SERVICE);
}
/**
* Create a new {@link Health} instance with a specific status code.
* @return a new {@link Health} instance
*/
public static Health status(String statusCode) {
return status(new Status(statusCode));
}
/**
* Create a new {@link Health} instance with a specific {@link Status}.
* @return a new {@link Health} instance
*/
public static Health status(Status status) {
return new Health(status, null);
}
}

View File

@ -38,9 +38,9 @@ public class MongoHealthIndicator extends AbstractHealthIndicator {
}
@Override
protected void doHealthCheck(Health health) throws Exception {
protected Health doHealthCheck() throws Exception {
CommandResult result = this.mongoTemplate.executeCommand("{ serverStatus: 1 }");
health.up().withDetail("version", result.getString("version"));
return Health.up().withDetail("version", result.getString("version"));
}
}

View File

@ -66,14 +66,14 @@ public class OrderedHealthAggregator extends AbstractHealthAggregator {
}
@Override
protected Status aggregateStatus(List<Status> status) {
protected Status aggregateStatus(List<Status> candidates) {
// If no status is given return UNKNOWN
if (status.size() == 0) {
if (candidates.size() == 0) {
return Status.UNKNOWN;
}
// Sort given Status instances by configured order
Collections.sort(status, new StatusComparator(this.statusOrder));
return status.get(0);
Collections.sort(candidates, new StatusComparator(this.statusOrder));
return candidates.get(0);
}
/**

View File

@ -41,17 +41,19 @@ public class RabbitHealthIndicator extends AbstractHealthIndicator {
}
@Override
protected void doHealthCheck(Health health) throws Exception {
health.up().withDetail("version",
this.rabbitTemplate.execute(new ChannelCallback<String>() {
protected Health doHealthCheck() throws Exception {
return Health.up().withDetail("version", getVersion());
}
@Override
public String doInRabbit(Channel channel) throws Exception {
Map<String, Object> serverProperties = channel.getConnection()
.getServerProperties();
return serverProperties.get("version").toString();
}
}));
private String getVersion() {
return this.rabbitTemplate.execute(new ChannelCallback<String>() {
@Override
public String doInRabbit(Channel channel) throws Exception {
Map<String, Object> serverProperties = channel.getConnection()
.getServerProperties();
return serverProperties.get("version").toString();
}
});
}
}

View File

@ -40,12 +40,12 @@ public class RedisHealthIndicator extends AbstractHealthIndicator {
}
@Override
protected void doHealthCheck(Health health) throws Exception {
RedisConnection connection = null;
protected Health doHealthCheck() throws Exception {
RedisConnection connection = RedisConnectionUtils
.getConnection(this.redisConnectionFactory);
try {
connection = RedisConnectionUtils.getConnection(this.redisConnectionFactory);
Properties info = connection.info();
health.up().withDetail("version", info.getProperty("redis_version"));
return Health.up().withDetail("version", info.getProperty("redis_version"));
}
finally {
RedisConnectionUtils.releaseConnection(connection,

View File

@ -35,7 +35,7 @@ import org.springframework.util.StringUtils;
* @author Dave Syer
* @author Christian Dupuis
*/
public class SimpleDataSourceHealthIndicator implements HealthIndicator {
public class SimpleDataSourceHealthIndicator extends AbstractHealthIndicator {
private DataSource dataSource;
@ -63,7 +63,6 @@ public class SimpleDataSourceHealthIndicator implements HealthIndicator {
/**
* Create a new {@link SimpleDataSourceHealthIndicator} using the specified
* datasource.
*
* @param dataSource the data source
*/
public SimpleDataSourceHealthIndicator(DataSource dataSource) {
@ -72,40 +71,39 @@ public class SimpleDataSourceHealthIndicator implements HealthIndicator {
}
@Override
public Health health() {
Health health = new Health();
health.up();
protected Health doHealthCheck() throws Exception {
if (this.dataSource == null) {
return Health.up().withDetail("database", "unknown");
}
return doDataSourceHealthCheck();
}
String product = "unknown";
if (this.dataSource != null) {
private Health doDataSourceHealthCheck() throws Exception {
String product = getProduct();
Health health = Health.up().withDetail("database", product);
String query = detectQuery(product);
if (StringUtils.hasText(query)) {
try {
product = this.jdbcTemplate.execute(new ConnectionCallback<String>() {
@Override
public String doInConnection(Connection connection)
throws SQLException, DataAccessException {
return connection.getMetaData().getDatabaseProductName();
}
});
health.withDetail("database", product);
health = health.withDetail("hello",
this.jdbcTemplate.queryForObject(query, Object.class));
}
catch (DataAccessException ex) {
health.down().withException(ex);
}
String query = detectQuery(product);
if (StringUtils.hasText(query)) {
try {
health.withDetail("hello",
this.jdbcTemplate.queryForObject(query, Object.class));
}
catch (Exception ex) {
health.down().withException(ex);
}
catch (Exception ex) {
return Health.down().withDetail("database", product).withException(ex);
}
}
return health;
}
private String getProduct() {
return this.jdbcTemplate.execute(new ConnectionCallback<String>() {
@Override
public String doInConnection(Connection connection) throws SQLException,
DataAccessException {
return connection.getMetaData().getDatabaseProductName();
}
});
}
protected String detectQuery(String product) {
String query = this.query;
if (!StringUtils.hasText(query)) {

View File

@ -20,7 +20,7 @@ import org.apache.solr.client.solrj.SolrServer;
/**
* {@link HealthIndicator} for Apache Solr
*
*
* @author Andy Wilkinson
* @since 1.1.0
*/
@ -33,9 +33,9 @@ public class SolrHealthIndicator extends AbstractHealthIndicator {
}
@Override
protected void doHealthCheck(Health health) throws Exception {
this.solrServer.ping();
health.up().withDetail("solrStatus",
this.solrServer.ping().getResponse().get("status"));
protected Health doHealthCheck() throws Exception {
Object status = this.solrServer.ping().getResponse().get("status");
return Health.up().withDetail("solrStatus", status);
}
}

View File

@ -35,7 +35,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
* @since 1.1.0
*/
@JsonInclude(Include.NON_EMPTY)
public class Status {
public final class Status {
/**
* Convenient constant value representing unknown state

View File

@ -25,8 +25,8 @@ package org.springframework.boot.actuate.health;
public class VanillaHealthIndicator extends AbstractHealthIndicator {
@Override
protected void doHealthCheck(Health health) throws Exception {
health.up();
protected Health doHealthCheck() throws Exception {
return Health.up();
}
}

View File

@ -65,7 +65,7 @@ public class HealthEndpointTests extends AbstractEndpointTests<HealthEndpoint> {
@Override
public Health health() {
return new Health().status(new Status("FINE"));
return Health.status("FINE");
}
};
}

View File

@ -51,7 +51,7 @@ public class HealthMvcEndpointTests {
@Test
public void up() {
when(this.endpoint.invoke()).thenReturn(new Health().up());
when(this.endpoint.invoke()).thenReturn(Health.up());
Object result = this.mvc.invoke();
assertTrue(result instanceof Health);
assertTrue(((Health) result).getStatus() == Status.UP);
@ -60,7 +60,7 @@ public class HealthMvcEndpointTests {
@SuppressWarnings("unchecked")
@Test
public void down() {
when(this.endpoint.invoke()).thenReturn(new Health().down());
when(this.endpoint.invoke()).thenReturn(Health.down());
Object result = this.mvc.invoke();
assertTrue(result instanceof ResponseEntity);
ResponseEntity<Health> response = (ResponseEntity<Health>) result;
@ -71,7 +71,7 @@ public class HealthMvcEndpointTests {
@SuppressWarnings("unchecked")
@Test
public void customMapping() {
when(this.endpoint.invoke()).thenReturn(new Health().status(new Status("OK")));
when(this.endpoint.invoke()).thenReturn(Health.status("OK"));
this.mvc.setStatusMapping(Collections.singletonMap("OK",
HttpStatus.INTERNAL_SERVER_ERROR));
Object result = this.mvc.invoke();

View File

@ -34,7 +34,7 @@ import static org.mockito.BDDMockito.given;
/**
* Tests for {@link CompositeHealthIndicator}
*
*
* @author Tyler J. Frederick
* @author Phillip Webb
* @author Christian Dupuis
@ -55,9 +55,9 @@ public class CompositeHealthIndicatorTests {
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
given(this.one.health()).willReturn(new Health().withDetail("1", "1"));
given(this.two.health()).willReturn(new Health().withDetail("2", "2"));
given(this.three.health()).willReturn(new Health().withDetail("3", "3"));
given(this.one.health()).willReturn(Health.unknown().withDetail("1", "1"));
given(this.two.health()).willReturn(Health.unknown().withDetail("2", "2"));
given(this.three.health()).willReturn(Health.unknown().withDetail("3", "3"));
this.healthAggregator = new OrderedHealthAggregator();
}
@ -72,9 +72,9 @@ public class CompositeHealthIndicatorTests {
Health result = composite.health();
assertThat(result.getDetails().size(), equalTo(2));
assertThat(result.getDetails(),
hasEntry("one", (Object) new Health().withDetail("1", "1")));
hasEntry("one", (Object) Health.unknown().withDetail("1", "1")));
assertThat(result.getDetails(),
hasEntry("two", (Object) new Health().withDetail("2", "2")));
hasEntry("two", (Object) Health.unknown().withDetail("2", "2")));
}
@Test
@ -88,11 +88,11 @@ public class CompositeHealthIndicatorTests {
Health result = composite.health();
assertThat(result.getDetails().size(), equalTo(3));
assertThat(result.getDetails(),
hasEntry("one", (Object) new Health().withDetail("1", "1")));
hasEntry("one", (Object) Health.unknown().withDetail("1", "1")));
assertThat(result.getDetails(),
hasEntry("two", (Object) new Health().withDetail("2", "2")));
hasEntry("two", (Object) Health.unknown().withDetail("2", "2")));
assertThat(result.getDetails(),
hasEntry("three", (Object) new Health().withDetail("3", "3")));
hasEntry("three", (Object) Health.unknown().withDetail("3", "3")));
}
@Test
@ -104,9 +104,9 @@ public class CompositeHealthIndicatorTests {
Health result = composite.health();
assertThat(result.getDetails().size(), equalTo(2));
assertThat(result.getDetails(),
hasEntry("one", (Object) new Health().withDetail("1", "1")));
hasEntry("one", (Object) Health.unknown().withDetail("1", "1")));
assertThat(result.getDetails(),
hasEntry("two", (Object) new Health().withDetail("2", "2")));
hasEntry("two", (Object) Health.unknown().withDetail("2", "2")));
}
@Test

View File

@ -0,0 +1,156 @@
/*
* Copyright 2012-2014 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
*
* http://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.boot.actuate.health;
import java.util.Collections;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertThat;
/**
* Tests for {@link Health}.
*
* @author Phillip Webb
*/
public class HealthTests {
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void statusMustNotBeNull() throws Exception {
this.thrown.expect(IllegalArgumentException.class);
this.thrown.expectMessage("Status must not be null");
new Health(null, null);
}
@Test
public void createWithStatus() throws Exception {
Health health = new Health(Status.UP, null);
assertThat(health.getStatus(), equalTo(Status.UP));
assertThat(health.getDetails().size(), equalTo(0));
}
@Test
public void createWithDetails() throws Exception {
Health health = new Health(Status.UP, Collections.singletonMap("a", "b"));
assertThat(health.getStatus(), equalTo(Status.UP));
assertThat(health.getDetails().get("a"), equalTo((Object) "b"));
}
@Test
public void equalsAndHashCode() throws Exception {
Health h1 = new Health(Status.UP, Collections.singletonMap("a", "b"));
Health h2 = new Health(Status.UP, Collections.singletonMap("a", "b"));
Health h3 = new Health(Status.UP, null);
assertThat(h1, equalTo(h1));
assertThat(h1, equalTo(h2));
assertThat(h1, not(equalTo(h3)));
assertThat(h1.hashCode(), equalTo(h1.hashCode()));
assertThat(h1.hashCode(), equalTo(h2.hashCode()));
assertThat(h1.hashCode(), not(equalTo(h3.hashCode())));
}
@Test
public void withException() throws Exception {
RuntimeException ex = new RuntimeException("bang");
Health health = new Health(Status.UP, Collections.singletonMap("a", "b"))
.withException(ex);
assertThat(health.getDetails().get("a"), equalTo((Object) "b"));
assertThat(health.getDetails().get("error"),
equalTo((Object) "java.lang.RuntimeException: bang"));
}
@Test
public void withDetails() throws Exception {
Health health = new Health(Status.UP, Collections.singletonMap("a", "b"))
.withDetail("c", "d");
assertThat(health.getDetails().get("a"), equalTo((Object) "b"));
assertThat(health.getDetails().get("c"), equalTo((Object) "d"));
}
@Test
public void unknownWithDetails() throws Exception {
Health health = Health.unknown().withDetail("a", "b");
assertThat(health.getStatus(), equalTo(Status.UNKNOWN));
assertThat(health.getDetails().get("a"), equalTo((Object) "b"));
}
@Test
public void unknown() throws Exception {
Health health = Health.unknown();
assertThat(health.getStatus(), equalTo(Status.UNKNOWN));
assertThat(health.getDetails().size(), equalTo(0));
}
@Test
public void upWithDetails() throws Exception {
Health health = Health.up().withDetail("a", "b");
assertThat(health.getStatus(), equalTo(Status.UP));
assertThat(health.getDetails().get("a"), equalTo((Object) "b"));
}
@Test
public void up() throws Exception {
Health health = Health.up();
assertThat(health.getStatus(), equalTo(Status.UP));
assertThat(health.getDetails().size(), equalTo(0));
}
@Test
public void downWithException() throws Exception {
RuntimeException ex = new RuntimeException("bang");
Health health = Health.down(ex);
assertThat(health.getStatus(), equalTo(Status.DOWN));
assertThat(health.getDetails().get("error"),
equalTo((Object) "java.lang.RuntimeException: bang"));
}
@Test
public void down() throws Exception {
Health health = Health.down();
assertThat(health.getStatus(), equalTo(Status.DOWN));
assertThat(health.getDetails().size(), equalTo(0));
}
@Test
public void outOfService() throws Exception {
Health health = Health.outOfService();
assertThat(health.getStatus(), equalTo(Status.OUT_OF_SERVICE));
assertThat(health.getDetails().size(), equalTo(0));
}
@Test
public void statusCode() throws Exception {
Health health = Health.status("UP");
assertThat(health.getStatus(), equalTo(Status.UP));
assertThat(health.getDetails().size(), equalTo(0));
}
@Test
public void status() throws Exception {
Health health = Health.status(Status.UP);
assertThat(health.getStatus(), equalTo(Status.UP));
assertThat(health.getDetails().size(), equalTo(0));
}
}

View File

@ -42,10 +42,10 @@ public class OrderedHealthAggregatorTests {
@Test
public void defaultOrder() {
Map<String, Health> healths = new HashMap<String, Health>();
healths.put("h1", new Health(Status.DOWN));
healths.put("h2", new Health(Status.UP));
healths.put("h3", new Health(Status.UNKNOWN));
healths.put("h4", new Health(Status.OUT_OF_SERVICE));
healths.put("h1", Health.status(Status.DOWN));
healths.put("h2", Health.status(Status.UP));
healths.put("h3", Health.status(Status.UNKNOWN));
healths.put("h4", Health.status(Status.OUT_OF_SERVICE));
assertEquals(Status.DOWN, this.healthAggregator.aggregate(healths).getStatus());
}
@ -54,21 +54,21 @@ public class OrderedHealthAggregatorTests {
this.healthAggregator.setStatusOrder(Status.UNKNOWN, Status.UP,
Status.OUT_OF_SERVICE, Status.DOWN);
Map<String, Health> healths = new HashMap<String, Health>();
healths.put("h1", new Health(Status.DOWN));
healths.put("h2", new Health(Status.UP));
healths.put("h3", new Health(Status.UNKNOWN));
healths.put("h4", new Health(Status.OUT_OF_SERVICE));
healths.put("h1", Health.status(Status.DOWN));
healths.put("h2", Health.status(Status.UP));
healths.put("h3", Health.status(Status.UNKNOWN));
healths.put("h4", Health.status(Status.OUT_OF_SERVICE));
assertEquals(Status.UNKNOWN, this.healthAggregator.aggregate(healths).getStatus());
}
@Test
public void defaultOrderWithCustomStatus() {
Map<String, Health> healths = new HashMap<String, Health>();
healths.put("h1", new Health(Status.DOWN));
healths.put("h2", new Health(Status.UP));
healths.put("h3", new Health(Status.UNKNOWN));
healths.put("h4", new Health(Status.OUT_OF_SERVICE));
healths.put("h5", new Health(new Status("CUSTOM")));
healths.put("h1", Health.status(Status.DOWN));
healths.put("h2", Health.status(Status.UP));
healths.put("h3", Health.status(Status.UNKNOWN));
healths.put("h4", Health.status(Status.OUT_OF_SERVICE));
healths.put("h5", Health.status(new Status("CUSTOM")));
assertEquals(new Status("CUSTOM"), this.healthAggregator.aggregate(healths)
.getStatus());
}
@ -78,11 +78,11 @@ public class OrderedHealthAggregatorTests {
this.healthAggregator.setStatusOrder(Arrays.asList("DOWN", "OUT_OF_SERVICE",
"UP", "UNKNOWN", "CUSTOM"));
Map<String, Health> healths = new HashMap<String, Health>();
healths.put("h1", new Health(Status.DOWN));
healths.put("h2", new Health(Status.UP));
healths.put("h3", new Health(Status.UNKNOWN));
healths.put("h4", new Health(Status.OUT_OF_SERVICE));
healths.put("h5", new Health(new Status("CUSTOM")));
healths.put("h1", Health.status(Status.DOWN));
healths.put("h2", Health.status(Status.UP));
healths.put("h3", Health.status(Status.UNKNOWN));
healths.put("h4", Health.status(Status.OUT_OF_SERVICE));
healths.put("h5", Health.status(new Status("CUSTOM")));
assertEquals(Status.DOWN, this.healthAggregator.aggregate(healths).getStatus());
}

View File

@ -27,8 +27,10 @@ import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.jdbc.datasource.SingleConnectionDataSource;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@ -78,7 +80,7 @@ public class SimpleDataSourceHealthIndicatorTests {
this.indicator.setDataSource(this.dataSource);
this.indicator.setQuery("SELECT COUNT(*) from BAR");
Health health = this.indicator.health();
assertNotNull(health.getDetails().get("database"));
assertThat(health.getDetails().get("database"), notNullValue());
assertEquals(Status.DOWN, health.getStatus());
}