Couchbase 3 Migration - functional test migration issues

Hello. I am migrating my application from couchbase 2 to couchbase 3 client. In the past my entire functional test suite was integrated with couchbase-mock. After switching to new client API I can’t figure out how to make my application client connect to couchbase mock instance. My version 2 test setup created cluster instance as follows:

cluster = CouchbaseCluster.create(DefaultCouchbaseEnvironment.builder()
.bootstrapCarrierDirectPort(carrierPort)
.bootstrapHttpDirectPort(couchbaseMock.getHttpPort())
.build(), “couchbase://127.0.0.1”);

Version 3 API changed significantly and following implementation does not work for me:

ClusterEnvironment env = ClusterEnvironment.builder().build();
Set seedNodes = new HashSet<>(
Arrays.asList(SeedNode.create(“localhost”, Optional.of(httpPort), Optional.empty()),
SeedNode.create(“localhost”, Optional.of(carrierPort), Optional.empty())));
cluster = Cluster.connect(“localhost”, ClusterOptions.clusterOptions(bucketName, password).environment(env));

When I start my tests I receive errors when accessing bucket:
Connection refused: localhost/127.0.0.1:8091 - Check server ports and cluster encryption setting.
Connection refused: localhost/127.0.0.1:11210 - Check server ports and cluster encryption setting.

Can client 3 application be tested using couchbase-mock? If not what are other couchbase testing APIs that support functional test implementations?

Hi Andrzej,

If you’re using a recent version of SDK 3, you can specify a custom port directly in the connection string. Does this work for you?

String username = bucketName;
Cluster cluster = Cluster.connect("127.0.0.1:" + carrierPort, username, password);

If this doesn’t work, can you share the code you’re using to initialize the mock?

Note: By default the port is assumed to be a KV (previously called “carrier”) port. If you need to bootstrap against a manager (previously called “http”) port, append =manager to the port name, like: example.com:1234=manager.

Thanks,
David

There’s also Testcontainers. It’s a library for running real servers in Docker for integration testing. Kevin Wittek and Michael Nitchinger gave a great presentation on using Testcontainers with Couchbase at Couchbase Connect 2021.

Thank you David. That put me on the correct path. The solution that worked for me was to create comma delimited string with host:port values for both carrier and http ports. Below is the solution that worked for couchbase-mock 1.5.25 and java-client 3.2.3:

BucketConfiguration bucketConfiguration = new BucketConfiguration();
// define your bucket

ArrayList configList = new ArrayList();
configList.add(bucketConfiguration);

CouchbaseMock couchbaseMock = new CouchbaseMock(0, configList);
couchbaseMock.start();
couchbaseMock.waitForStartup();
int httpPort = couchbaseMock.getHttpPort();

// get memcache service port
URIBuilder builder = new URIBuilder();
builder.setScheme(“http”).setHost(“localhost”).setPort(httpPort).setPath(“mock/get_mcports”).setParameter(“bucket”, bucketName);

HttpClient clientCb = HttpClientBuilder.create().build();
HttpResponse response = clientCb.execute(new HttpGet(builder.build()));
int status = response.getStatusLine().getStatusCode();

if (status == 200) {
String rawBody = EntityUtils.toString(response.getEntity());
ArrayList ports = (ArrayList) JsonUtils.GSON.fromJson(rawBody, Map.class).get(“payload”);
int carrierPort = ((Double) ports.get(0)).intValue();

Cluster cluster = Cluster.connect("127.0.0.1:" + carrierPort + ",127.0.0.1:" + httpPort + "=manager",
                ClusterOptions.clusterOptions(
                        PasswordAuthenticator.builder().onlyEnablePlainSaslMechanism().username(bucketName)
                                .password(password).build()));

}

Hi Andrzej,

I’m glad you got it working. Have you tried without the duplicate addresses? I’d expect you only need one. No need to specify both the “carrier” and “http” ports. If you specify one, the SDK will use it to connect and discover the other.

Thanks,
David