Add Randomized Responses to Moco API Mock Server
This guide shows how to extend Moco with a custom RandomHandler that selects one of several predefined responses at runtime, providing full Java code, helper methods, and a usage example for building more realistic mock APIs.
Problem
When using the Moco API to create mock services, some endpoints need to return one of several predefined responses chosen at random. Moco does not provide this capability out of the box.
Solution – RandomHandler
A custom ResponseHandler is implemented by extending AbstractResponseHandler. The handler stores an immutable list of delegate ResponseHandler objects and selects one of them for each request.
package com.fun.moco.support;
import com.fun.frame.SourceCode;
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;
/** Random response handler */
public class RandomHandler extends AbstractResponseHandler {
private final ImmutableList<ResponseHandler> handlers;
private RandomHandler(final Iterable<ResponseHandler> handlers) {
this.handlers = copyOf(handlers);
}
/** Create a handler from a non‑empty collection of delegates */
public static ResponseHandler newSeq(final Iterable<ResponseHandler> handlers) {
checkArgument(Iterables.size(handlers) > 0, "Sequence contents should not be null");
return new RandomHandler(handlers);
}
/** Choose a delegate at random and write its response */
@Override
public void writeToResponse(final SessionContext context) {
int index = SourceCode.getRandomInt(handlers.size()) - 1; // getRandomInt returns 1‑based value
handlers.get(index).writeToResponse(context);
}
/** Apply a Moco configuration to every delegate */
@Override
public ResponseHandler apply(final MocoConfig config) {
if (config.isFor(MocoConfig.RESPONSE_ID)) {
return super.apply(config);
}
FluentIterable<ResponseHandler> transformed = from(copyOf(handlers)).transform(applyConfig(config));
return new RandomHandler(transformed.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);
}
};
}
}Key methods
writeToResponse(SessionContext)– selects a random delegate using SourceCode.getRandomInt and forwards the call. apply(MocoConfig) – propagates a Moco configuration to each delegate, returning a new RandomHandler with the transformed list. newSeq(Iterable<ResponseHandler>) – static factory that validates the input and creates the handler.
Convenient static factory methods
Three overloads are provided to build a RandomHandler from common data types. They convert the inputs to ResponseHandler instances (using an assumed textToResource() utility) and then delegate to RandomHandler.newSeq.
/** Random response from plain strings */
static ResponseHandler random(String content, String... contents) {
return RandomHandler.newSeq(
FluentIterable.from(asIterable(content, contents)).transform(textToResource())
);
}
/** Random response from JSON objects */
static ResponseHandler random(JSONObject json, JSONObject... jsons) {
return RandomHandler.newSeq(
FluentIterable.from(
asIterable(json.toString(), jsons.toList().stream().map(x -> x.toString()).toArray(String[]::new))
).transform(textToResource())
);
}
/** Random response from existing handlers */
static ResponseHandler random(ResponseHandler handler, ResponseHandler... handlers) {
return RandomHandler.newSeq(asIterable(handler, handlers));
}Usage example
Integrate the handler into a Moco server configuration. Each request to /find will receive one of the three strings chosen at random.
server.get(urlOnly("/find")).response(
random("43242=342", "e343=fdsf", "3242")
);This approach adds randomised response behaviour without modifying the core Moco library, enabling more realistic test scenarios.
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.
