Skip to content

Commit

Permalink
[📚docs] revisit docs 3/3 Testing + Advanced (#6096)
Browse files Browse the repository at this point in the history
* rework the "testing" section

* link to nullability higher up
  • Loading branch information
martinbonnin authored Aug 5, 2024
1 parent a18a291 commit 555f8b3
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 61 deletions.
32 changes: 1 addition & 31 deletions docs/source/advanced/experimental-websockets.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -111,34 +111,4 @@ The above uses the default retry algorithm:
* Wait until the network is available if you configured a [NetworkMonitor](network-connectivity).
* Or use exponential backoff else.

To customize the retry logic more, use `retryOnErrorInterceptor`:

```kotlin
val apolloClient = ApolloClient.Builder()
.retryOnErrorInterceptor(MyRetryOnErrorInterceptor())
.build()

class MyRetryOnErrorInterceptor : ApolloInterceptor {
object RetryException : Exception()

override fun <D : Operation.Data> intercept(request: ApolloRequest<D>, chain: ApolloInterceptorChain): Flow<ApolloResponse<D>> {
var attempt = 0
return chain.proceed(request).onEach {
if (request.retryOnError == true && it.exception != null && it.exception is ApolloNetworkException) {
throw RetryException
} else {
attempt = 0
}
}.retryWhen { cause, _ ->
if (cause is RetryException) {
attempt++
delay(2.0.pow(attempt).seconds)
true
} else {
// Not a RetryException, probably a programming error, pass it through
false
}
}
}
}
```
To customize the retry logic more, see the [network monitoring page](../advanced/network-connectivity#customizing-the-retry-algorithm).
43 changes: 25 additions & 18 deletions docs/source/advanced/network-connectivity.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -54,27 +54,34 @@ When a `NetworkMonitor` is configured, `retryOnError` uses `NetworkMonitor.waitF

### Customizing the retry algorithm

You can customize the retry algorithm further by defining you own interceptor:
You can customize the retry algorithm further by defining your own interceptor:

```kotlin
internal class MyRetryInterceptor(private val networkMonitor: NetworkMonitor?): ApolloInterceptor {
val apolloClient = ApolloClient.Builder()
.retryOnErrorInterceptor(MyRetryOnErrorInterceptor())
.build()

class MyRetryOnErrorInterceptor : ApolloInterceptor {
object RetryException : Exception()

override fun <D : Operation.Data> intercept(request: ApolloRequest<D>, chain: ApolloInterceptorChain): Flow<ApolloResponse<D>> {
// Disable Apollo's built-in retry mechanism
val newRequest = request.newBuilder().retryOnError(false).build()
return chain.proceed(newRequest)
.onEach {
if (it.exception != null && it.exception.shouldRetry()) {
throw RetryException
}
}.retryWhen { cause, _->
if (cause is RetryException) {
// Add your logic here
true
} else {
// Programming error, re-throw it
false
}
}
var attempt = 0
return chain.proceed(request).onEach {
if (request.retryOnError == true && it.exception != null && it.exception is ApolloNetworkException) {
throw RetryException
} else {
attempt = 0
}
}.retryWhen { cause, _ ->
if (cause is RetryException) {
attempt++
delay(2.0.pow(attempt).seconds)
true
} else {
// Not a RetryException, probably a programming error, pass it through
false
}
}
}
}
```
Expand Down
2 changes: 1 addition & 1 deletion docs/source/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@
"Batching operations": "/advanced/query-batching"
},
"Development & Testing": {
"Android Studio plugin": "/testing/android-studio-plugin",
"Testing overview": "/testing/overview",
"Mocking HTTP responses": "/testing/mocking-http-responses",
"Mocking GraphQL responses": "/testing/mocking-graphql-responses",
"Data builders": "/testing/data-builders",
"Android Studio plugin": "/testing/android-studio-plugin",
"Apollo Debug Server": "/testing/apollo-debug-server"
},
"Advanced": {
Expand Down
13 changes: 7 additions & 6 deletions docs/source/essentials/errors.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
title: Error handling
---

<Note>

Starting with version 4.0.0, Apollo Kotlin offers a way to handle errors automatically at parsing time. Fields that are nullable only for error purposes can also be generated as non-null in Kotlin. Read ["handling nullability"](../advanced/nullability) for more details.

</Note>

## `ApolloResponse`

Use `ApolloResponse.data` to check if the server returned data:
Expand Down Expand Up @@ -130,9 +136,4 @@ For an example, it is possible for a person to not have a starship:
}
```

In that case, `starship` is a true null and not an error.

### Handling GraphQL errors at parsing time

Because making the difference between true nulls and error nulls is cumbersome, Apollo Kotlin offers a way to handle errors automatically at parsing time. Fields that are nullable only for error purposes can also be generated as non-null in Kotlin. Read ["handling nullability"](../advanced/nullability) for more details.

In that case, `starship` is a true null and not an error.
2 changes: 0 additions & 2 deletions docs/source/testing/mocking-graphql-responses.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ title: Mocking GraphQL responses

`QueueTestNetworkTransport` is a high-level test API that lets you specify the GraphQL responses that are returned by your `ApolloClient` instance.

> See also [`MockServer`](./mocking-http-responses), which creates a full HTTP server and helps test specific server behaviors, such as error cases, HTTP headers, and timeouts.
Add the dependency to your project's `build.gradle` file:

```kotlin title="build.gradle[.kts]"
Expand Down
7 changes: 6 additions & 1 deletion docs/source/testing/mocking-http-responses.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ title: Mocking HTTP responses (experimental)

`MockServer` implements an HTTP server that you can use to mock responses. It's useful for testing specific server behaviors, such as error cases, HTTP headers, and timeouts. Using it requires minimal changes to your production code, because you only need to change your `serverUrl`.

> See also [`TestNetworkTransport`](./mocking-graphql-responses), which handles mocking at the GraphQL level instead of the HTTP level.

<Note>

Apollo Kotlin MockServer is developed in a separate repository. Head to /~https://github.com/apollographql/apollo-kotlin-mockserver for API docs and comprehensive documentation.

</Note>

Add the dependency to your project's `build.gradle` file:

Expand Down
4 changes: 2 additions & 2 deletions docs/source/testing/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ Apollo Kotlin provides the following tools to help with testing your code:

- [`MockServer`](./mocking-http-responses) (experimental): an HTTP server that you can use to mock any responses
- [`TestNetworkTransport`](./mocking-graphql-responses) (experimental): lets you specify the GraphQL responses returned by `ApolloClient`
- [Test builders](./test-builders) (experimental): help instantiate your model classes by providing a DSL
- [Data builders](./data-builders) (experimental): help instantiate your model classes by providing a DSL

`MockServer` creates a full HTTP server. It requires minimal changes to your production code (you only need to change `serverUrl`), which means you can use the same `ApolloClient` for tests and production. `MockServer` is also useful for testing specific server behaviors, such as error cases, HTTP headers, and timeouts.

`TestNetworkTransport` bypasses HTTP calls altogether and returns predefined GraphQL responses. It requires more modifications to your production code, but you can use it in lighter tests that don't need to create a server. You can use test builders to instantiate the data in the responses.
`TestNetworkTransport` bypasses HTTP calls altogether and returns predefined GraphQL responses. It requires more modifications to your production code, but you can use it in lighter tests that don't need to create a server. You can use data builders to instantiate the data in the responses.

0 comments on commit 555f8b3

Please sign in to comment.