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.
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.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
