Skip to content

Commit

Permalink
Merge pull request #90 from speekha/develop
Browse files Browse the repository at this point in the history
Publish 1.2.0
  • Loading branch information
speekha authored Mar 31, 2020
2 parents 5948284 + 0852e6f commit 7ecc010
Show file tree
Hide file tree
Showing 125 changed files with 2,935 additions and 1,625 deletions.
12 changes: 6 additions & 6 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ commands:
- build-mocker-{{ .Branch }}-{{ .Revision }}
- run:
name: Build
command: ./gradlew << parameters.module >>:clean << parameters.module >>:assemble << parameters.module >>:sourcesJar << parameters.module >>:dokkaJar --stacktrace
command: ./gradlew --no-daemon << parameters.module >>:clean << parameters.module >>:assemble << parameters.module >>:sourcesJar << parameters.module >>:dokkaJar --stacktrace
- save_cache:
key: build-<< parameters.module >>-{{ .Branch }}-{{ .Revision }}
paths:
Expand Down Expand Up @@ -81,7 +81,7 @@ jobs:
- restore_sources_and_gradle
- run:
name: Download Dependencies
command: ./gradlew androidDependencies --stacktrace
command: ./gradlew --no-daemon androidDependencies --stacktrace
- save_cache:
paths:
- ~/.gradle
Expand All @@ -103,7 +103,7 @@ jobs:
- restore_sources_and_gradle
- run:
name: Build
command: ./gradlew mocker:clean mocker:assemble mocker:sourcesJar mocker:dokkaJar --stacktrace
command: ./gradlew --no-daemon mocker:clean mocker:assemble mocker:sourcesJar mocker:dokkaJar --stacktrace
- save_cache:
key: build-mocker-{{ .Branch }}-{{ .Revision }}
paths:
Expand Down Expand Up @@ -150,7 +150,7 @@ jobs:
- build-jackson-adapter-{{ .Branch }}-{{ .Revision }}
- run:
name: Build
command: ./gradlew demo:clean demo:assembleRelease demo:testReleaseUnitTest --stacktrace
command: ./gradlew --no-daemon demo:clean demo:assembleRelease demo:testReleaseUnitTest demo:lint --stacktrace
- store_test_results:
path: demo/build/test-results
- store_artifacts:
Expand All @@ -175,7 +175,7 @@ jobs:
- restore_all_caches
- run:
name: Tests
command: ./gradlew tests:test tests:jacocoTestReport test:sendCoverageToCodacy --stacktrace
command: ./gradlew --no-daemon tests:test tests:jacocoTestReport test:sendCoverageToCodacy --stacktrace
- store_artifacts:
path: tests/build/reports
destination: reports
Expand All @@ -194,7 +194,7 @@ jobs:
- restore_sources_and_gradle
- run:
name: Check quality
command: ./gradlew detekt ktlintCheck lint --stacktrace
command: ./gradlew --no-daemon detekt ktlintCheck --stacktrace
- store_artifacts:
path: mocker/build/reports
destination: reports/mocker
Expand Down
83 changes: 53 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# HttpMocker

[![Kotlin](https://img.shields.io/badge/kotlin-1.3.50-blue.svg)](http://kotlinlang.org)
[![Kotlin](https://img.shields.io/badge/kotlin-1.3.61-blue.svg)](http://kotlinlang.org)
[![CircleCI](https://circleci.com/gh/speekha/httpmocker/tree/develop.svg?style=shield)](https://circleci.com/gh/speekha/httpmocker/tree/develop)
[![Download](https://api.bintray.com/packages/speekha/httpmocker/mocker/images/download.svg)](https://bintray.com/speekha/httpmocker/mocker/_latestVersion)

Expand All @@ -24,7 +24,7 @@ can be reused later.
## Current Version

```gradle
httpmocker_version = '1.1.8'
httpmocker_version = '1.2.0'
```

## Gradle
Expand Down Expand Up @@ -57,46 +57,52 @@ repositories {

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 six 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 would prefer to use XML instead
of JSON, a SAX-based parser allows to do it. If you choose one of these options, all you need to add is the corresponding
`implementation` line in your gradle file:
most commonly used serialization libraries and on a custom implementations (no third party dependency):
* Jackson
* Gson
* Moshi
* Kotlinx serialization)
* Custom JSON implementation
* Custom Sax-based implementation
This should allow you to choose one matching what you already use in your application (in order to prevent
duplicate libraries in your classpath, like Jackson and GSON). If you would prefer to use XML instead
of JSON, the SAX-based parser allows to do it. If you choose one of these options, all you need to add is the
corresponding `implementation` line in your gradle file:

```gradle
// Parses JSON scenarios using Jackson
implementation "fr.speekha.httpmocker:jackson-adapter:1.1.8"
implementation "fr.speekha.httpmocker:jackson-adapter:1.2.0"
// Parses JSON scenarios using Gson
implementation "fr.speekha.httpmocker:gson-adapter:1.1.8"
implementation "fr.speekha.httpmocker:gson-adapter:1.2.0"
// Parses JSON scenarios using Moshi
implementation "fr.speekha.httpmocker:moshi-adapter:1.1.8"
implementation "fr.speekha.httpmocker:moshi-adapter:1.2.0"
// Parses JSON scenarios using Kotlinx Serialization
implementation "fr.speekha.httpmocker:kotlinx-adapter:1.1.8"
implementation "fr.speekha.httpmocker:kotlinx-adapter:1.2.0"
// Parses JSON scenarios using a custom JSON parser
implementation "fr.speekha.httpmocker:custom-adapter:1.1.8"
implementation "fr.speekha.httpmocker:custom-adapter:1.2.0"
// Parses XML scenarios using a custom SAX parser
implementation "fr.speekha.httpmocker:sax-adapter:1.1.8"
implementation "fr.speekha.httpmocker:sax-adapter:1.2.0"
```

If none of those options suits your needs or if you would prefer to only use dynamic mocks, you can add
If none of those options suit 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):

```gradle
implementation "fr.speekha.httpmocker:mocker:1.1.8"
implementation "fr.speekha.httpmocker:mocker:1.2.0"
```

#### External dependencies

* HttpMocker is a mocking library for OkHttp connections, so it depends on OkHttp 3.14.4.
* HttpMocker is a mocking library for OkHttp connections, so it depends on OkHttp 3.14.7.
* It also depends on the SLF4J API for logging.
* JSON parsers depend on their respective external libraries: Jackson 2.10.0, Gson 2.8.6, Moshi
1.9.1 or KotlinX serialization 0.13.0.
* JSON parsers depend on their respective external libraries: Jackson 2.10.3, Gson 2.8.6, Moshi
1.9.2 or KotlinX serialization 0.20.0.

### Proguard rules

Expand All @@ -110,10 +116,10 @@ The custom and moshi parsers are immune to obfuscation because they do not use a
## Quickstart

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:

is to add it to your OkHttp client. Here's an example with minimal configuration of dynamic mocks
using the Java-friendly builder syntax:
```kotlin
val interceptor = MockResponseInterceptor.Builder()
val interceptor = Builder()
.useDynamicMocks{
ResponseDescriptor(code = 200, body = "Fake response body")
}
Expand All @@ -123,6 +129,20 @@ is to add it to your OkHttp client. Here's an example with minimal configuration
.addInterceptor(interceptor)
.build()
```

You can write the same thing in a more Kotlin-friendly style:
```kotlin
val interceptor = mockInterceptor {
useDynamicMocks{
ResponseDescriptor(code = 200, body = "Fake response body")
}
setInterceptorStatus(ENABLED)
}
val client = OkHttpClient.Builder()
.addInterceptor(interceptor)
.build()
```

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
Expand All @@ -133,19 +153,22 @@ 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:
```kotlin
val interceptor = MockResponseInterceptor.Builder()
.parseScenariosWith(mapper)
.decodeScenarioPathWith(filingPolicy)
.loadFileWith { context.assets.open(it) }
.setInterceptorStatus(ENABLED)
.saveScenariosIn(File(rootFolder))
.addFakeNetworkDelay(50L)
.build()
val interceptor = mockInterceptor {
parseScenariosWith(mapper)
decodeScenarioPathWith(filingPolicy)
loadFileWith {
context.assets.open(it)
}
setInterceptorStatus(ENABLED)
saveScenariosIn(File(rootFolder))
addFakeNetworkDelay(50L)
}
```

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
with). You also need to provide the `FilingPolicy` 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.

Expand Down
29 changes: 8 additions & 21 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.jlleitschuh.gradle.ktlint.reporter.ReporterType

buildscript {

Expand All @@ -25,13 +24,13 @@ buildscript {
}

dependencies {
classpath 'com.android.tools.build:gradle:3.5.0'
classpath 'com.android.tools.build:gradle:3.6.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
classpath "org.jetbrains.dokka:dokka-android-gradle-plugin:$dokka_version"
classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:$bintray_version"
classpath "org.jfrog.buildinfo:build-info-extractor-gradle:$artifactory_version"
classpath "org.jlleitschuh.gradle:ktlint-gradle:8.2.0"
classpath "org.jlleitschuh.gradle:ktlint-gradle:$ktlint_version"
}
}

Expand Down Expand Up @@ -60,7 +59,10 @@ allprojects {
version = "0.34.2"
verbose = true
android = false
reporters = [ReporterType.PLAIN, ReporterType.CHECKSTYLE]
reporters {
reporter "plain"
reporter "checkstyle"
}
additionalEditorconfigFile = file("../.editorconfig")

filter {
Expand All @@ -70,23 +72,8 @@ allprojects {
}
}

subprojects {
// tasks.withType<Test> {
// maxParallelForks = (Runtime.getRuntime().availableProcessors() / 2).takeIf { it > 0 } ?: 1
// }

apply plugin: "io.gitlab.arturbosch.detekt"

detekt {
config = files("../detekt.yml")
parallel = true
reports {
xml { enabled = true }
html { enabled = true }
}
}
}

task clean(type: Delete) {
delete rootProject.buildDir
}

apply from: 'gradle/detekt.gradle'
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,35 @@

package fr.speekha.httpmocker.custom

import fr.speekha.httpmocker.Mapper
import fr.speekha.httpmocker.custom.parser.JsonParser
import fr.speekha.httpmocker.custom.parser.adapters.MatcherAdapter
import fr.speekha.httpmocker.custom.serializer.toJson
import fr.speekha.httpmocker.model.Matcher
import fr.speekha.httpmocker.serialization.JSON_FORMAT
import fr.speekha.httpmocker.serialization.Mapper

/**
* A mapper using custom JSON parsing to serialize/deserialize scenarios.
*/
class CustomMapper : Mapper {

private val adapter = MatcherAdapter()
override val supportedFormat: String = JSON_FORMAT

override fun deserialize(payload: String): List<Matcher> = JsonStringReader(payload).parseJson(adapter)
private val adapter =
MatcherAdapter()

private fun JsonStringReader.parseJson(matcherMapper: MatcherAdapter): List<Matcher> {
override fun deserialize(payload: String): List<Matcher> = JsonParser(
payload
).parseJson(adapter)

private fun JsonParser.parseJson(matcherMapper: MatcherAdapter): List<Matcher> {
beginList()
val list = populateList(matcherMapper)
endList()
return list
}

private fun JsonStringReader.populateList(matcherMapper: MatcherAdapter): List<Matcher> =
private fun JsonParser.populateList(matcherMapper: MatcherAdapter): List<Matcher> =
mutableListOf<Matcher>().also { list ->
while (hasNext()) {
list += matcherMapper.fromJson(this)
Expand Down
Loading

0 comments on commit 7ecc010

Please sign in to comment.