Implementing a Custom Cycle ResponseHandler in Moco for Repeated Requests

This article explains how to create a custom CycleHandle response handler for the Moco framework to simulate repeated responses, provides the full Java implementation, demonstrates Groovy helper methods for easy usage, and briefly discusses Groovy's JVM compatibility advantages.

FunTester
FunTester
FunTester
Implementing a Custom Cycle ResponseHandler in Moco for Repeated Requests

When using the Moco testing framework, the official documentation mentions a cycle() method for returning an array of responses, but the API does not actually expose such a method. The missing functionality is needed in scenarios that require repeated responses, such as order submission retries or resource deletion loops.

To fill this gap, a custom CycleHandle class is implemented by extending AbstractResponseHandler. The class stores an immutable list of ResponseHandler objects, tracks the current index, and overrides writeToResponse to forward the request to the next handler in a round‑robin fashion. It also overrides apply to transform the handlers according to the provided MocoConfig and return a new CycleHandle instance.

package com.fun.moco.support;

import com.github.dreamhead.moco.MocoConfig;
import com.github.dreamhead.moco.ResponseHandler;
import com.github.dreamhead.moco.handler.AbstractResponseHandler;
import com.github.dreamhead.moco.internal.SessionContext;
import com.google.common.base.Function;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.FluentIterable.from;
import static com.google.common.collect.ImmutableList.copyOf;

/**
 * Custom response handler that cycles through a list of handlers.
 */
@SuppressWarnings("all")
public class CycleHandle extends AbstractResponseHandler {
    private final ImmutableList<ResponseHandler> handlers;
    private int index;

    private CycleHandle(final Iterable<ResponseHandler> handlers) {
        this.handlers = copyOf(handlers);
    }

    public static ResponseHandler newSeq(final Iterable<ResponseHandler> handlers) {
        checkArgument(Iterables.size(handlers) > 0, "Sequence contents should not be null");
        return new CycleHandle(handlers);
    }

    @Override
    public void writeToResponse(final SessionContext context) {
        handlers.get((index++) % handlers.size()).writeToResponse(context);
    }

    @Override
    public ResponseHandler apply(final MocoConfig config) {
        if (config.isFor(MocoConfig.RESPONSE_ID)) {
            return super.apply(config);
        }
        FluentIterable<ResponseHandler> transformedResources =
            from(copyOf(handlers)).transform(applyConfig(config));
        return new CycleHandle(transformedResources.toList());
    }

    private Function<ResponseHandler, ResponseHandler> applyConfig(final MocoConfig config) {
        return new Function<ResponseHandler, ResponseHandler>() {
            @Override
            public ResponseHandler apply(final ResponseHandler input) {
                return input.apply(config);
            }
        };
    }
}

In Groovy, two convenience static methods are provided to create the cycling handler more succinctly. The first overload accepts a primary String and a var‑args of additional strings, converting them into resources via asIterable and textToResource(). The second overload accepts a primary ResponseHandler and additional handlers.

/**
 * Cycle response for string contents.
 */
static ResponseHandler cycle(String content, String... contents) {
    CycleHandle.newSeq(
        FluentIterable.from(asIterable(content, contents))
                      .transform(textToResource())
    );
}

/**
 * Cycle response for existing handlers.
 */
static ResponseHandler cycle(final ResponseHandler handler, final ResponseHandler... handlers) {
    CycleHandle.newSeq(asIterable(handler, handlers));
}

These utilities allow developers to simulate repeated responses without modifying the Moco core library. The article also notes that Groovy, being a JVM‑based dynamic language, offers excellent compatibility with Java libraries and a low learning curve, making it a convenient choice for writing such test scripts.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavatestingGroovyMoCoCycleResponseHandler
FunTester
Written by

FunTester

10k followers, 1k articles | completely useless

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.