3

I'm doing acceptance testing for a microservice that connects to couchbase, elasticsearch and Kafka. I don't want to use any embedded instance or any test cluster. I want to be able to mock the couchbase calls, but at the same should test the N1QL queries that I've written.

For elasticsearch, I'm using Wiremock and mocking the REST calls. But for couchbase, I don't know the structure of the rest calls that the client makes to the database.

Also, I went ahead and wrote a test case. With that, I mocked all the REST calls that couchbase made, from the error message. But I see that couchbase connects to a netty channel, how do I mock the channel?

If not that, is there a better way to mock couchbase?

RxComputationScheduler- 3|ERROR||||c.c.c.d.i.n.u.c.D.rejectedExecution|181|Failed to submit a listener notification task. Event loop shut down?
java.util.concurrent.RejectedExecutionException: event executor terminated
at com.couchbase.client.deps.io.netty.util.concurrent.SingleThreadEventExecutor.reject(SingleThreadEventExecutor.java:796)
at com.couchbase.client.deps.io.netty.util.concurrent.SingleThreadEventExecutor.offerTask(SingleThreadEventExecutor.java:336)
at com.couchbase.client.deps.io.netty.util.concurrent.SingleThreadEventExecutor.addTask(SingleThreadEventExecutor.java:329)
at com.couchbase.client.deps.io.netty.util.concurrent.SingleThreadEventExecutor.execute(SingleThreadEventExecutor.java:739)
at com.couchbase.client.deps.io.netty.util.concurrent.DefaultPromise.safeExecute(DefaultPromise.java:760)
at com.couchbase.client.deps.io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:428)
at com.couchbase.client.deps.io.netty.util.concurrent.DefaultPromise.setFailure(DefaultPromise.java:113)
at com.couchbase.client.deps.io.netty.channel.DefaultChannelPromise.setFailure(DefaultChannelPromise.java:87)
at com.couchbase.client.core.endpoint.AbstractEndpoint$3.call(AbstractEndpoint.java:381)
at com.couchbase.client.core.endpoint.AbstractEndpoint$3.call(AbstractEndpoint.java:374)
at rx.internal.operators.SingleOperatorOnErrorResumeNext$2.onError(SingleOperatorOnErrorResumeNext.java:69)
at rx.internal.operators.SingleTimeout$TimeoutSingleSubscriber$OtherSubscriber.onError(SingleTimeout.java:133)
at rx.Single$1.call(Single.java:477)
at rx.Single$1.call(Single.java:473)
at rx.Single.subscribe(Single.java:1979)
at rx.Single$18.call(Single.java:2518)
at rx.Single$18.call(Single.java:2505)
at rx.internal.operators.SingleTimeout$TimeoutSingleSubscriber.call(SingleTimeout.java:110)
at rx.internal.schedulers.EventLoopsScheduler$EventLoopWorker$2.call(EventLoopsScheduler.java:189)
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)

This is the error that I'm getting.

varshavp27
  • 167
  • 1
  • 1
  • 14

3 Answers3

3

If I were determined to do this, I would do the mocking at the level of the SDK. Create your own versions of its objects, like Connection and Bucket and whatever else (I don't usually work with Java.) Then find a place to inject this alternate DB access layer for testing purposes. That way you have your own application code working with your own mock code, giving you full control. Trying to do the mocking at the level of the HTTP calls the SDK makes to the database strikes me as relying too much on obscure material that Couchbase does not make public.

Johan Larson
  • 1,880
  • 1
  • 11
  • 14
3

Another option might be the use a Testcontainers module. There's one for Couchbase here: https://www.testcontainers.org/modules/databases/couchbase/

An example from the site to build a bucket:

public class SomeTest {

    @Rule
    public CouchbaseContainer couchbase = new CouchbaseContainer()
             .withClusterAdmin("admin", "secret")
             .withNewBucket(DefaultBucketSettings.builder()
                        .enableFlush(true)
                        .name("bucket-name")
                        .password("secret")
                        .quota(100)
                        .type(BucketType.COUCHBASE)
                        .build());

    @Test
    public void someTestMethod() {
        Bucket bucket = couchbase.getCouchbaseCluster().openBucket("bucket-name");

        // ... interact with client as if using Couchbase normally
    }
}
Matthew Groves
  • 25,181
  • 9
  • 71
  • 121
2

Have you had a look at CouchbaseMock? https://github.com/couchbase/CouchbaseMock

From the readme:

CouchbaseMock is a test server implementing some of the memcached protocol which is used by some SDKs (including the C SDK) for basic testing. While it is recommended that testing be done against the real server, CouchbaseMock is useful as being self contained (there is no need to install it to the system) and for allowing extra instrumentation.

Matthew Groves
  • 25,181
  • 9
  • 71
  • 121