Migrate Couchbase tests to JUnit 5.

Closes #664
This commit is contained in:
Mark Paluch
2023-05-15 11:32:12 +02:00
parent 545d957031
commit ea17c12f93
10 changed files with 304 additions and 309 deletions

View File

@@ -17,94 +17,91 @@ package example.springdata.couchbase.repository;
import static org.assertj.core.api.Assertions.*; import static org.assertj.core.api.Assertions.*;
import example.springdata.couchbase.model.Airline;
import example.springdata.couchbase.util.CouchbaseAvailableRule;
import java.util.List; import java.util.List;
import org.junit.Before; import org.junit.jupiter.api.BeforeEach;
import org.junit.ClassRule; import org.junit.jupiter.api.Test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.couchbase.core.CouchbaseOperations; import org.springframework.data.couchbase.core.CouchbaseOperations;
import org.springframework.test.context.junit4.SpringRunner;
import example.springdata.couchbase.model.Airline;
import example.springdata.couchbase.util.EnabledOnCouchbaseAvailable;
/** /**
* Integration tests showing basic CRUD operations through {@link AirlineRepository}. * Integration tests showing basic CRUD operations through {@link AirlineRepository}.
* *
* @author Denis Rosa * @author Denis Rosa
*/ */
@RunWith(SpringRunner.class)
@SpringBootTest @SpringBootTest
@EnabledOnCouchbaseAvailable
public class AirlineRepositoryIntegrationTests { public class AirlineRepositoryIntegrationTests {
@ClassRule // @Autowired
public static CouchbaseAvailableRule COUCHBASE = CouchbaseAvailableRule.onLocalhost(); AirlineRepository airlineRepository;
@Autowired AirlineRepository airlineRepository; @Autowired
CouchbaseOperations couchbaseOperations;
@Autowired CouchbaseOperations couchbaseOperations; @BeforeEach
public void before() {
if (couchbaseOperations.existsById().one("LH")) {
couchbaseOperations.removeById().one("LH");
}
}
@Before /**
public void before() { * The derived query executes a N1QL query emitting a single element.
if (couchbaseOperations.existsById().one("LH")) { */
couchbaseOperations.removeById().one("LH"); @Test
} public void shouldFindAirlineN1ql() {
}
/** List<Airline> airlines = airlineRepository.findByIata("TQ");
* The derived query executes a N1QL query emitting a single element. assertThat(airlines.get(0).getCallsign()).isEqualTo("TXW");
*/ }
@Test
public void shouldFindAirlineN1ql() {
List<Airline> airlines = airlineRepository.findByIata("TQ"); /**
assertThat(airlines.get(0).getCallsign()).isEqualTo("TXW"); * The derived query executes a N1QL query and the emitted element is used to invoke
} * {@link org.springframework.data.repository.reactive.ReactiveCrudRepository#findById(Object)} for an Id-based lookup.
* Queries without a result do not emit a value.
*/
@Test
public void shouldFindById() {
/** Airline airline = airlineRepository.findByIata("TQ").get(0);
* The derived query executes a N1QL query and the emitted element is used to invoke assertThat(airlineRepository.findById(airline.getId()).isPresent());
* {@link org.springframework.data.repository.reactive.ReactiveCrudRepository#findById(Object)} for an Id-based }
* lookup. Queries without a result do not emit a value.
*/
@Test
public void shouldFindById() {
Airline airline = airlineRepository.findByIata("TQ").get(0); /**
assertThat(airlineRepository.findById(airline.getId()).isPresent()); * Find all {@link Airline}s applying the {@code airlines/all} view.
} */
@Test
public void shouldFindByView() {
/** List<Airline> airlines = airlineRepository.findAllBy();
* Find all {@link Airline}s applying the {@code airlines/all} view.
*/
@Test
public void shouldFindByView() {
List<Airline> airlines = airlineRepository.findAllBy(); assertThat(airlines).hasSizeGreaterThan(100);
}
assertThat(airlines).hasSizeGreaterThan(100); /**
} * Created elements are emitted by the
* {@link org.springframework.data.repository.reactive.ReactiveCrudRepository#save(Object)} method.
*/
@Test
public void shouldCreateAirline() {
/** Airline airline = new Airline();
* Created elements are emitted by the
* {@link org.springframework.data.repository.reactive.ReactiveCrudRepository#save(Object)} method.
*/
@Test
public void shouldCreateAirline() {
Airline airline = new Airline(); airline.setId("LH");
airline.setIata("LH");
airline.setIcao("DLH");
airline.setCallsign("Lufthansa");
airline.setName("Lufthansa");
airline.setCountry("Germany");
airline.setId("LH"); airlineRepository.save(airline);
airline.setIata("LH");
airline.setIcao("DLH");
airline.setCallsign("Lufthansa");
airline.setName("Lufthansa");
airline.setCountry("Germany");
airlineRepository.save(airline); assertThat(airlineRepository.findById("LH")).contains(airline);
}
assertThat(airlineRepository.findById("LH")).contains(airline);
}
} }

View File

@@ -17,111 +17,108 @@ package example.springdata.couchbase.repository;
import static org.assertj.core.api.Assertions.*; import static org.assertj.core.api.Assertions.*;
import example.springdata.couchbase.model.Airline; import org.junit.jupiter.api.BeforeEach;
import example.springdata.couchbase.util.CouchbaseAvailableRule; import org.junit.jupiter.api.Test;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.couchbase.core.CouchbaseOperations; import org.springframework.data.couchbase.core.CouchbaseOperations;
import org.springframework.test.context.junit4.SpringRunner;
import example.springdata.couchbase.model.Airline;
import example.springdata.couchbase.util.EnabledOnCouchbaseAvailable;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
/** /**
* Integration tests showing basic CRUD operations through {@link ReactiveAirlineRepository} * Integration tests showing basic CRUD operations through {@link ReactiveAirlineRepository}
* *
* @author Mark Paluch * @author Mark Paluch
*/ */
@RunWith(SpringRunner.class)
@SpringBootTest @SpringBootTest
@EnabledOnCouchbaseAvailable
public class ReactiveAirlineRepositoryIntegrationTests { public class ReactiveAirlineRepositoryIntegrationTests {
@ClassRule // @Autowired
public static CouchbaseAvailableRule COUCHBASE = CouchbaseAvailableRule.onLocalhost(); ReactiveAirlineRepository airlineRepository;
@Autowired ReactiveAirlineRepository airlineRepository; @Autowired
CouchbaseOperations couchbaseOperations;
@Autowired CouchbaseOperations couchbaseOperations; @BeforeEach
public void before() {
if (couchbaseOperations.existsById().one("LH")) {
couchbaseOperations.removeById().one("LH");
}
}
@Before /**
public void before() { * The derived query executes a N1QL query emitting a single element.
if (couchbaseOperations.existsById().one("LH")) { */
couchbaseOperations.removeById().one("LH"); @Test
} public void shouldFindAirlineN1ql() {
}
/** airlineRepository.findByIata("TQ") //
* The derived query executes a N1QL query emitting a single element. .as(StepVerifier::create) //
*/ .assertNext(it -> {
@Test assertThat(it.getCallsign()).isEqualTo("TXW");
public void shouldFindAirlineN1ql() { }).verifyComplete();
}
airlineRepository.findByIata("TQ") // /**
.as(StepVerifier::create) // * The derived query executes a N1QL query and the emitted element is used to invoke
.assertNext(it -> { * {@link org.springframework.data.repository.reactive.ReactiveCrudRepository#findById(Object)} for an Id-based lookup.
assertThat(it.getCallsign()).isEqualTo("TXW"); * Queries without a result do not emit a value.
}).verifyComplete(); */
} @Test
public void shouldFindById() {
/** Mono<Airline> airline = airlineRepository.findByIata("TQ") //
* The derived query executes a N1QL query and the emitted element is used to invoke .map(Airline::getId) //
* {@link org.springframework.data.repository.reactive.ReactiveCrudRepository#findById(Object)} for an Id-based .flatMap(airlineRepository::findById);
* lookup. Queries without a result do not emit a value.
*/
@Test
public void shouldFindById() {
Mono<Airline> airline = airlineRepository.findByIata("TQ") // airline.as(StepVerifier::create) //
.map(Airline::getId) // .assertNext(it -> {
.flatMap(airlineRepository::findById);
airline.as(StepVerifier::create) // assertThat(it.getCallsign()).isEqualTo("TXW");
.assertNext(it -> { }).verifyComplete();
assertThat(it.getCallsign()).isEqualTo("TXW"); }
}).verifyComplete();
} /**
* Find all {@link Airline}s applying the {@code airlines/all} view.
*/
@Test
public void shouldFindAll() {
airlineRepository.findAllBy().count() //
.as(StepVerifier::create) //
.assertNext(count -> {
/** assertThat(count).isGreaterThan(100);
* Find all {@link Airline}s applying the {@code airlines/all} view. }).verifyComplete();
*/ }
@Test
public void shouldFindAll() {
airlineRepository.findAllBy().count() //
.as(StepVerifier::create) //
.assertNext(count -> {
assertThat(count).isGreaterThan(100); /**
}).verifyComplete(); * Created elements are emitted by the
} * {@link org.springframework.data.repository.reactive.ReactiveCrudRepository#save(Object)} method.
*/
@Test
public void shouldCreateAirline() {
/** Airline airline = new Airline();
* Created elements are emitted by the
* {@link org.springframework.data.repository.reactive.ReactiveCrudRepository#save(Object)} method.
*/
@Test
public void shouldCreateAirline() {
Airline airline = new Airline(); airline.setId("LH");
airline.setIata("LH");
airline.setIcao("DLH");
airline.setCallsign("Lufthansa");
airline.setName("Lufthansa");
airline.setCountry("Germany");
airline.setId("LH"); Mono<Airline> airlineMono = airlineRepository.save(airline) //
airline.setIata("LH"); .map(Airline::getId) //
airline.setIcao("DLH"); .flatMap(airlineRepository::findById);
airline.setCallsign("Lufthansa");
airline.setName("Lufthansa");
airline.setCountry("Germany");
Mono<Airline> airlineMono = airlineRepository.save(airline) // airlineMono.as(StepVerifier::create) //
.map(Airline::getId) // .expectNext(airline) //
.flatMap(airlineRepository::findById); .verifyComplete();
}
airlineMono.as(StepVerifier::create) //
.expectNext(airline) //
.verifyComplete();
}
} }

View File

@@ -17,21 +17,18 @@ package example.springdata.couchbase.template;
import static org.assertj.core.api.Assertions.*; import static org.assertj.core.api.Assertions.*;
import example.springdata.couchbase.model.Airline; import org.junit.jupiter.api.BeforeEach;
import example.springdata.couchbase.util.CouchbaseAvailableRule; import org.junit.jupiter.api.Test;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.couchbase.core.CouchbaseOperations; import org.springframework.data.couchbase.core.CouchbaseOperations;
import org.springframework.data.couchbase.core.ReactiveCouchbaseOperations; import org.springframework.data.couchbase.core.ReactiveCouchbaseOperations;
import org.springframework.test.context.junit4.SpringRunner;
import example.springdata.couchbase.model.Airline;
import example.springdata.couchbase.util.EnabledOnCouchbaseAvailable;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
/** /**
* Integration tests showing basic CRUD operations through * Integration tests showing basic CRUD operations through
@@ -40,61 +37,57 @@ import org.springframework.test.context.junit4.SpringRunner;
* @author Mark Paluch * @author Mark Paluch
* @author Denis Rosa * @author Denis Rosa
*/ */
@RunWith(SpringRunner.class)
@SpringBootTest @SpringBootTest
@EnabledOnCouchbaseAvailable
public class ReactiveJavaCouchbaseOperationsIntegrationTests { public class ReactiveJavaCouchbaseOperationsIntegrationTests {
@ClassRule // @Autowired
public static CouchbaseAvailableRule COUCHBASE = CouchbaseAvailableRule.onLocalhost(); ReactiveCouchbaseOperations operations;
@Autowired @Autowired
ReactiveCouchbaseOperations operations; CouchbaseOperations couchbaseOperations;
@Autowired @BeforeEach
CouchbaseOperations couchbaseOperations; public void before() {
if (couchbaseOperations.existsById().one("LH")) {
couchbaseOperations.removeById().one("LH");
}
}
@Before /**
public void before() { * Find all {@link Airline}s applying the _class filter .
if (couchbaseOperations.existsById().one("LH")) { */
couchbaseOperations.removeById().one("LH"); @Test
} public void shouldFindByAll() {
} operations.findByQuery(Airline.class).all() //
.count() //
.as(StepVerifier::create) //
.assertNext(count -> {
/** assertThat(count).isGreaterThan(100);
* Find all {@link Airline}s applying the _class filter . }) //
*/ .verifyComplete();
@Test }
public void shouldFindByAll() {
operations.findByQuery(Airline.class).all() //
.count() //
.as(StepVerifier::create) //
.assertNext(count -> {
assertThat(count).isGreaterThan(100); /**
}) // * Created elements are emitted by {@link ReactiveCouchbaseOperations#upsertById(Class)} )}.
.verifyComplete(); */
} @Test
public void shouldCreateAirline() {
Airline airline = new Airline();
/** airline.setId("LH");
* Created elements are emitted by {@link ReactiveCouchbaseOperations#upsertById(Class)} )}. airline.setIata("LH");
*/ airline.setIcao("DLH");
@Test airline.setCallsign("Lufthansa");
public void shouldCreateAirline() { airline.setName("Lufthansa");
Airline airline = new Airline(); airline.setCountry("Germany");
airline.setId("LH"); Mono<Airline> airlineMono = operations.upsertById(Airline.class).one(airline) //
airline.setIata("LH"); .map(Airline::getId) //
airline.setIcao("DLH"); .flatMap(id -> operations.findById(Airline.class).one(id));
airline.setCallsign("Lufthansa");
airline.setName("Lufthansa");
airline.setCountry("Germany");
Mono<Airline> airlineMono = operations.upsertById(Airline.class) airlineMono.as(StepVerifier::create) //
.one(airline) // .expectNext(airline).verifyComplete();
.map(Airline::getId) // }
.flatMap(id -> operations.findById(Airline.class).one(id));
airlineMono.as(StepVerifier::create) //
.expectNext(airline).verifyComplete();
}
} }

View File

@@ -22,12 +22,6 @@
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>compile</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@@ -17,28 +17,15 @@ package com.example.demo;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.core.type.AnnotatedTypeMetadata;
import example.springdata.couchbase.util.CouchbaseAvailableRule;
/** /**
* @author Michael Reiche * @author Michael Reiche
*/ */
@SpringBootApplication @SpringBootApplication
@Conditional(DemoApplication.CouchbaseAvailable.class)
public class DemoApplication { public class DemoApplication {
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args); SpringApplication.run(DemoApplication.class, args);
} }
static class CouchbaseAvailable implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return CouchbaseAvailableRule.onLocalhost().isAvailable();
}
}
} }

View File

@@ -15,25 +15,20 @@
*/ */
package com.example.demo; package com.example.demo;
import org.junit.ClassRule;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;
import example.springdata.couchbase.util.CouchbaseAvailableRule; import example.springdata.couchbase.util.EnabledOnCouchbaseAvailable;
/** /**
* @author Michael Reiche * @author Michael Reiche
* @author Christoph Strobl * @author Christoph Strobl
*/ */
@SpringBootTest @SpringBootTest(classes = DemoApplication.class)
@ContextConfiguration(classes = DemoApplication.class) @EnabledOnCouchbaseAvailable
class DemoApplicationTests { class DemoApplicationTests {
@ClassRule //
public static CouchbaseAvailableRule COUCHBASE = CouchbaseAvailableRule.onLocalhost();
@Test @Test
void contextLoads() { void contextLoads() {
} }

View File

@@ -1,5 +1,6 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <project xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
@@ -15,8 +16,9 @@
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>org.junit.jupiter</groupId>
<artifactId>junit</artifactId> <artifactId>junit-jupiter-api</artifactId>
<scope>compile</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@@ -1,82 +0,0 @@
/*
* Copyright 2017-2021 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 example.springdata.couchbase.util;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.time.Duration;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BiConsumer;
import javax.net.SocketFactory;
import org.junit.AssumptionViolatedException;
import org.junit.rules.ExternalResource;
/**
* Rule to check Couchbase server availability. If Couchbase is not running, tests are skipped.
*
* @author Mark Paluch
*/
public class CouchbaseAvailableRule extends ExternalResource {
private final String host;
private final int port;
private final Duration timeout = Duration.ofSeconds(1);
private CouchbaseAvailableRule(String host, int port) {
this.host = host;
this.port = port;
}
/**
* Create a new rule requiring Couchbase running on {@code localhost} on {@code 8091}.
*
* @return the test rule.
*/
public static CouchbaseAvailableRule onLocalhost() {
return new CouchbaseAvailableRule("localhost", 8091);
}
@Override
protected void before() throws Throwable {
check((b, throwable) -> {
if (throwable != null) {
throw new AssumptionViolatedException(
String.format("Couchbase not available on on %s:%d. Skipping tests.", host, port), throwable);
}
});
}
public boolean isAvailable() {
AtomicBoolean b = new AtomicBoolean();
check((avail, t) -> b.set(avail));
return b.get();
}
private void check(BiConsumer<Boolean, Throwable> c) {
try (Socket socket = SocketFactory.getDefault().createSocket()) {
socket.connect(new InetSocketAddress(host, port), Math.toIntExact(timeout.toMillis()));
c.accept(true, null);
} catch (IOException e) {
c.accept(false, e);
}
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright 2020-2021 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 example.springdata.couchbase.util;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.junit.jupiter.api.extension.ExtendWith;
/**
* {@code @EnabledOnCouchbaseAvailable} is used to signal that the annotated test class or test method is only <em>enabled</em>
* if Couchbase is running.
* <p/>
* When applied at the class level, all test methods within that class will be enabled.
*
* @author Mark Paluch
*/
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@ExtendWith(EnabledOnCouchbaseCondition.class)
public @interface EnabledOnCouchbaseAvailable {
/**
* Couchbase host.
*/
String host() default "localhost";
/**
* Couchbase port number.
*/
int port() default 8091;
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright 2020-2021 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 example.springdata.couchbase.util;
import static org.junit.jupiter.api.extension.ConditionEvaluationResult.*;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import org.junit.jupiter.api.extension.ConditionEvaluationResult;
import org.junit.jupiter.api.extension.ExecutionCondition;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.platform.commons.util.AnnotationUtils;
/**
* {@link ExecutionCondition} for {@link EnabledOnCouchbaseCondition @EnabledOnCouchbaseAvailable}.
*
* @author Mark Paluch
* @see EnabledOnCouchbaseCondition
*/
class EnabledOnCouchbaseCondition implements ExecutionCondition {
private static final ConditionEvaluationResult ENABLED_BY_DEFAULT = enabled("@EnabledOnCouchbaseAvailable is not present");
@Override
public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
var optional = AnnotationUtils.findAnnotation(context.getElement(), EnabledOnCouchbaseAvailable.class);
if (optional.isEmpty()) {
return ENABLED_BY_DEFAULT;
}
var annotation = optional.get();
try (var socket = new Socket()) {
socket.connect(new InetSocketAddress(annotation.host(), annotation.port()), 100);
return enabled(String.format("Connection successful to Couchbase at %s:%d", annotation.host(), annotation.port()));
} catch (IOException e) {
return disabled(
String.format("Cannot connect to Couchbase at %s:%d (%s)", annotation.host(), annotation.port(), e));
}
}
}