Skip to content
HttpMocker is a simple HTTP mocking library written in Kotlin to quickly and easily handle offline modes in your apps
Kotlin Shell
Branch: develop
Clone or download
David Blanc
David Blanc Formatting
Latest commit 27b78b6 Aug 21, 2019


Kotlin CircleCI Download

codebeat badge Codacy Badge CodeFactor

HttpMocker is a very lightweight Kotlin library that allows to mock HTTP calls relying on the OkHttp library.

  • It can be used for unit or integration tests, so your tests can rely on predefined responses and not execute actual calls to servers, thus avoiding the risk of unpredictable results due to network failure or server errors.

  • It can also be used to implement an offline mode in your application for debugging or demo purposes.

Thanks to the MockResponseInterceptor, network calls will not be dispatched to the network but read from JSON configuration files or computed dynamically instead. The interceptor will also allow to record scenarios so they can be reused later.

Current Version

httpmocker_version = '1.1.6'



For stable versions, check that you have the jcenter repository.

// Add Jcenter to your repositories if needed
repositories {


For Snapshot versions, check that you have the OJO snapshot repository.

// Add to your repositories if needed
repositories {
    maven { url '' }


Adding HttpMocker

This library contains two parts: a core module handling the mock logic, and an additional adapter to parse the scenario files for static mocks. Currently, there are five possible options that are provided for parsing, based on some of the most commonly used libraries for JSON parsing (Jackson, Gson, Moshi, Kotlinx serialization) and a custom implementation (no third party dependency), so you can choose the one matching what you already use in your application (this will help you prevent duplicate libraries in your classpath, like Jackson and GSON). If you choose one of these options, all you need to add is the corresponding implementation line in your gradle file:

// Parses JSON scenarios using Jackson
implementation "fr.speekha.httpmocker:jackson-adapter:1.1.6"

// Parses JSON scenarios using Gson
implementation "fr.speekha.httpmocker:gson-adapter:1.1.6"

// Parses JSON scenarios using Moshi
implementation "fr.speekha.httpmocker:moshi-adapter:1.1.6"

// Parses JSON scenarios using Kotlinx Serialization
implementation "fr.speekha.httpmocker:kotlinx-adapter:1.1.6"

// Parses JSON scenarios using a custom JSON parser
implementation "fr.speekha.httpmocker:custom-adapter:1.1.6"

If none of those options suits your needs or if you would prefer to only use dynamic mocks, you can add the main dependency to your project (using static mocks will require that you provide your own implementation of the Mapper class):

implementation "fr.speekha.httpmocker:mocker:1.1.6"

External dependencies

  • HttpMocker is a mocking library for OkHttp connections, so it depends on OkHttp 3.14.2.
  • It also depends on the SLF4J API for logging.
  • JSON parsers depend on their respective external libraries: Jackson 2.9.9, Gson 2.8.5, Moshi 1.8.0 or KotlinX serialization 0.11.0.

Proguard rules

Since Jackson, Gson or Kotlinx serialization use some type of introspection or annotation processing to parse JSON streams, it is recommended to keep the mapping classes unobfuscated. You can refer to the file included in the demo app for an example of required rules.

The custom and moshi parsers are immune to obfuscation because they do not use any introspection.


Mocking http calls relies on a simple Interceptor: MockResponseInterceptor. All you need to set it up is to add it to your OkHttp client. Here's an example with minimal configuration using dynamic mocks:

    val interceptor = MockResponseInterceptor.Builder()
            ResponseDescriptor(code = 200, body = "Fake response body")
    val client = OkHttpClient.Builder()

If your interceptor is disabled, it will not interfere with actual network calls. If it is enabled, it will need to find scenarios to mock the HTTP calls. Dynamic mocks imply that you have to provide the response for each request programmatically, which allows you to define stateful responses (identical calls could lead to different answers based on what the user did in between these calls). The response can be provided by implementing the RequestCallback interface or you can simply provide a lambda function to do the computation.

Another option is to use static mocks. Static mocks are scenarios stored as static files. Here is an example for an Android app using static mocks, with a few more options:

    val interceptor = MockResponseInterceptor.Builder()
        .loadFileWith { }

In this example, we decided to store the scenarios in the assets folder of the app (but you could also have them as resources in your classpath and use the Classloader to access them or even store them in a certain folder and access that folder with any File API you're comfortable with). You also need to provide the FilePolicy you want to use: that policy defines which file to check to find a match for a request. A few policies are provided in the library, but you can also define your own.

Additionally, you need to provide a Mapper to parse the JSON scenario files. In theory, scenarios do not have to be stored as JSON: you could use XML if you prefered, or any other format, as long as you provide your own Mapper class to serialize and deserialize the business objects. As far as this lib is concerned though, a few mappers are available out of the box, but they only handle JSON format for the moment and are based on Jackson, Gson, Moshi and Kotlinx serialization. They are provided in specific modules so you can choose one based on the JSON library you already use, thus limiting the risk for duplicate libraries serving the same purpose in your app. An implementation based on a custom JSON parser that does not need any other dependencies is also available.

Static and dynamic scenarios can be used together. Several dynamic callbacks can be added to the interceptor, but only one static configuration is allowed. Dynamic callbacks will be used first to find a suitable mock, and if none is found, the static configuration will be tested next.

If you choose the mixed mode, requests that can not be answered by a predefined scenario will actually be executed. Hence the mixed mode: responses can come from a scenario file (or dynamic mock) or from an actual HTTP call.

Finally, the interceptor also has a recording mode. This mode allows you to record scenarios without interfering with your request. If you choose this mode to produce your static scenarios, you will have to provide a root folder where the scenarios should be stored. Also, you should realize that all request and responses attributes will be recorded. Generally, you will want to review the resulting scenarios and clean them up a bit manually. For instance, each request will be recorded with its HTTP method, its path, each header or parameter, its body. But all those details might not be very important to you. Maybe all you care about is the URL and method, in which case, you can delete all the superfluous criteria manually.

Building static scenarios

Answering a request with a static mock is done in two steps:

  • First, if the interceptor is enabled (or in mixed mode), it will try to compute a file name were the appropriate scenario should be stored. Based on the filing policy you chose, those files can be organized in a lot of different ways: all in the same folder, in separate folders matching the URL path, ignoring or not the server hostname.

  • Second, once the file is found, its content will be loaded, and a more exact match will have to be found. Scenario files contain a list of "Matchers", that is a list of request patterns and corresponding responses. Based on the request it is trying to answer, the interceptor is going to scan through all the request declarations and stop as soon as it finds one that matches the situation.

When writing a request pattern, the elements included are supposed to be found in the requests to match. The more elements, the more precise the match has to be. The less elements, the more permissive the match. A request can even be omitted altogether (in this case, all requests match):

  • When specifying a method, matching request have to use the same HTTP method.
  • When specifying query parameters, matching requests must have at least all these parameters (but can have more).
  • When specifying headers, matching request must have all the same headers (but can have more).

Here is an example of scenario in JSON form:

    "request": {
      "method": "post",
      "headers": {
        "myHeader": "myHeaderValue"
      "params": {
        "myParam": "myParamValue"
      "body": ".*1.*"
    "response": {
      "delay": 50,
      "code": 200,
      "media-type": "application/json",
      "headers": {
        "myHeader": "headerValue1"
      "body-file": "body_content.txt"
  }, {
       "response": {
         "delay": 50,
         "code": 200,
         "media-type": "application/json",
         "headers": {
           "myHeader": "headerValue2"
         "body": "No body here"

In this example, a POST request on the corresponding URL, including a query param "myParam" with the value "myParamValue", a header "myHeader" with the value "myHeaderValue" and a body containing the digit '1' (based on the regex used as body) will match the first case: it will be answered a HTTP 200 response of type "application/json", with a header "myHeader" of value "headerValue1". The body for this response will be found in a nearby file name "body_content.txt". In any other cases, the request will be answered with the second response: a HTTP 200 response with "headerValue2" as header and a simple string "No body here" as body.


Follow me

Follow me


Introductory blog post on Kt. Academy

Kotlin Weekly mentioned it

You can’t perform that action at this time.