Implementing a Cycle ResponseHandler in Moco for Repeating Requests

This article explains how to create a custom CycleHandle response handler for the Moco framework, providing full Java source code and Groovy usage examples to enable cyclic responses in scenarios such as order submission or resource deletion.

FunTester
FunTester
FunTester
Implementing a Cycle ResponseHandler in Moco for Repeating Requests

When using the Moco testing framework, the official documentation mentions a cycle() method for returning an array of responses in a loop, but the method is not present in the public API. To fill this gap, a custom CycleHandle class is implemented by extending AbstractResponseHandler.

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;

/**
 * Cycle response handler that returns responses in a round‑robin fashion.
 */
@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);
            }
        };
    }
}

Two convenience static methods are provided for Groovy (and can be converted to Java) to create a cyclic response handler from either raw strings or existing ResponseHandler instances.

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

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

These utilities allow developers to define a sequence of responses that Moco will serve repeatedly, which is useful for testing scenarios that involve multiple request attempts such as order submissions, resource deletions, or retry logic.

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.