Dive into Mocking Your Microservice Dependencies with Skyramp
Tags: testing, microservices, api, devops
Published: 2023-12-14 15:34:30

Welcome back, fellow developers! In today's blog post, we're diving into the world of microservices and discussing a crucial aspect of their development and testing: mocking dependencies. Distributed applications built on microservices offer unparalleled flexibility and scalability, but they also bring challenges when it comes to managing dependencies during development and testing. 

Fear not! [Skyramp](https://www.skyramp.dev) provides effective ways to mock your microservice dependencies, making your development process smoother and more efficient. This blog post will cover the necessary inputs and many choices you have at your disposal for mocking dependencies with Skyramp.

## Mocking for the Uninitiated

Mocking is a technique used in software development to simulate the behavior of certain components, usually external dependencies, during the testing phase. The purpose of mocking is to isolate the unit of code being tested and control the inputs and outputs of external dependencies. Instead of using the actual implementations of these dependencies, developers create "mock" objects or functions that mimic the expected behavior without executing the real logic.

### Why Do Developers Mock Services?

In a microservices architecture, where a system is composed of multiple independently deployable services, mocking becomes particularly important for several reasons:

* **Isolation**: Microservices often rely on external services, databases, or APIs. When developers are testing a specific microservice, they want to isolate it from these external dependencies. Mocking allows them to simulate the behavior of these dependencies, focusing solely on the code under test.

* **Consistency**: Given that microservices have dependencies on other microservices or third-party APIs, mocking enables developers to test each microservice without relying on the availability or consistency of external services. This is crucial for maintaining a fast and reliable testing pipeline.

* **Controlled Testing Environment**: Mocking provides control over the responses from external services, allowing developers to test different scenarios, error conditions, or edge cases that might be challenging to reproduce with real services. This helps uncover potential issues and improve the overall robustness of the microservices.

* **Parallel Development**: In a microservices environment, different teams might be working on different services simultaneously. Mocking enables parallel development by allowing teams to develop and test their microservices independently, even if other services they depend on are still under development.

* **Cost and Resource Efficiency**: Connecting to real services, especially external services, during every test can be resource-intensive and slow down the development and testing process. Mocking eliminates the need to make actual requests, improving the efficiency of the testing cycle.

* **Fault Injection**: Mocking allows developers to simulate error conditions or faults in external services, helping them assess how well their microservices handle failures or unexpected behaviors in the dependencies. This is crucial for building resilient microservices.

* **Early Testing**: Mocking facilitates testing early in the development process when certain dependencies might not be fully implemented or available. It allows developers to start testing components even before all external services are ready for integration.

Mocking microservice dependencies is a key practice in  developing distributed applications to ensure efficient and effective testing, isolate units of code, and streamline the development workflow in a distributed and complex architecture. Let's take a look at all the ways you can mock dependencies for your microservices with Skyramp.

## Mocking with Skyramp

Mocking dependencies with Skyramp all starts with Skyramp's [Mocker](https://skyramp.dev/docs/docker/mocker/). Mocker is a solution for creating mock API services which run in-cluster for either [Kubernetes](https://https://kubernetes.io/) or [Docker Compose](https://docs.docker.com/compose/). In the [architecture diagram](https://skyramp.dev/docs/docker/reference/architecture/) below, you can see how [mock descriptions](https://www.skyramp.dev/docs/docker/mocker/mock-description/) can be applied to the Skyramp Worker to run the mocks.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gmg31xc5ijpcazjo83sn.png)

### Skyramp Clients

Skyramp offers multiple interfaces for mocking dependencies depending on your preference or workflow. Your options include:

1. The [command-line interface](https://skyramp.dev/docs/docker/reference/cli-commands/skyramp/) (CLI) for using Skyramp in a terminal.
2. The Visual Studio Code [extension](https://marketplace.visualstudio.com/items?itemName=skyramp.mocker-vscode) for using Skyramp in VSCode.
3. The Skyramp libraries for [Python](https://pypi.org/project/skyramp/) or [JavaScript](https://www.npmjs.com/package/@skyramp/skyramp) for making Skyramp calls from your own code.

### Supported Environments
To get started with mocking dependencies with Skyramp, your microservice must be running in one of these environments:

* **Docker Compose**: Docker Compose is used for defining and running multi-container Docker applications. You can configure your application's services in YAML and then start the services with a simple command.

* **Kubernetes**: Orchestrating and managing containerized distributed applications becomes more manageable with Kubernetes, providing scalability and resilience to your microservices.

### Service Protocols
Skyramp supports a number protocols for mocks to accommodate different microservices architectures. Some of the key protocols include:

* **gRPC**: If your microservices communicate using the gRPC protocol, Skyramp provides comprehensive mocking capabilities, ensuring a smooth testing experience.

* **REST**: For microservices adhering to a RESTful architecture, Skyramp supports robust mocking to facilitate thorough testing and development.

* **JSON-RPC WebSocket**: Skyramp extends its support to JSON-RPC over WebSocket, enabling developers to mock dependencies in real-time communication scenarios.

* **JSON-RPC HTTP**: When your microservices utilize JSON-RPC over HTTP for communication, Skyramp is equipped to support mocks for this protocol, offering flexibility in testing various scenarios.

### Choices for Mocking

1. **Generate a mock from an API definition**
Skyramp simplifies the process of mocking by allowing you to generate mocks directly from your API definitions, such as [OpenAPI](https://www.openapis.org/) or [Protobuf](https://protobuf.dev/). This means you can easily create realistic mocks that mimic the behavior of your actual microservices. With the Skyramp CLI, it's as easy as running `skyramp mocker generate ...` with the relevant inputs. See the [Skyramp Docs](https://skyramp.dev/docs/docker/mocker/how-to-mock-services/#generate-a-mock-from-user-input) for which flags to use based on your protocol. 

2. **Create a mock from scratch**
For more control over your mocks, Skyramp enables you to create mocks from scratch. This is useful when you need to tailor your mocks to specific scenarios or edge cases that may not be fully covered by the API definitions.  With the Skyramp CLI, it's as easy as running `skyramp init mock ...` and providing a protocol. See the [Skyramp Docs](https://skyramp.dev/docs/docker/mocker/how-to-mock-services/#write-a-mock-from-scratch) for the specific sub-commands.

3. **Configure mocks with data**
Mocking isn't just about mimicking endpoints, it's also about replicating real-world scenarios. With Skyramp, you can configure your mocks with realistic data, ensuring that your microservices are tested thoroughly under various conditions. See the [Skyramp Docs](https://www.skyramp.dev/docs/kubernetes/mocker/how-to-mock-services/#response-configuration) on how to configure responses for your mocks.

### What's in a Mock?

At a fundamental level, a Skyramp mock consists of an [endpoint](https://skyramp.dev/docs/docker/mocker/how-to-mock-services/#endpoint-configuration), a [response](https://skyramp.dev/docs/docker/mocker/how-to-mock-services/#response-configuration), and a [mock](https://skyramp.dev/docs/docker/mocker/how-to-mock-services/#mock-configuration) configuration. Below is a sample mock description file as an example. You can read more details about Skyramp [mock descriptions](https://www.skyramp.dev/docs/docker/mocker/mock-description/) in the Skyramp Docs.

```yaml
version: v1
mock:
    description: routeguide
    responses:
        - responseName: ListFeatures
        - responseName: RecordRoute
        - responseName: RouteChat
          lossPercentage: 50
          delayConfig:
              minDelay: 1000
              maxDelay: 2000
    proxies:
        - endpointName: routeguide-svc-RouteGuide
          methodName: GetFeature
```

## Getting our Feet Wet: A Simple Example

Let's walk through a simple example to illustrate how easy it is to mock microservice dependencies with Skyramp. We will use a sandbox environment that already has Docker and the Skyramp CLI installed, so there is nothing you need to install locally. You may recognize elements of this example from [previous blog posts](https://dev.to/dangross/jump-into-microservices-testing-with-docker-compose-and-skyramp-18o6). Start by launching the sandbox environment in GitHub Codespaces:

[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/letsramp/sample-microservices/tree/docker-compose-demo?machine=standardLinux32gb)

In this example, we have microservices that communicate via REST, and we want to mock one of the dependent microservices for testing purposes. This particular distributed application is an e-commerce store and we want to mock the payment service for the checkout flow.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c38n01kj2eoub8fnnfhc.png)

Once the Codespace launches, you will see a VSCode window in your browser as shown above. The repo source files are pre-loaded and a terminal pane is available. Let's start by changing directories:

```bash
cd skyramp/docker-compose
```
Next, let's bring up the containers, which include the Skyramp Worker container and the application containers.

```bash
docker compose up &
```
Now that the application services are running, let's take a look at the mock we generated previously for our payment service. It is called `payment-service-k8s.yaml` under the `mocks` folder, which you can navigate to and open in VSCode. Notice the configuration parameters of the mock, including `services`, `endpoints`, and `responseValues` as discussed earlier.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/khoam23o5vbze3kh2wd0.png)

Let's apply the mock to the Skyramp Worker:

```bash
skyramp mocker apply payment-service-k8s --address localhost:35142
```
Then, we can verify the mock is running:

```bash
skyramp mocker status --address localhost:35142
```

You should see output like this:

```bash
Applied mocks at the address 'localhost:35142': 
+----+-----------------+-----------------+----------+-------------+
| ID | ADDRESS         | SERVICE         | ENDPOINT | METHOD      |
+----+-----------------+-----------------+----------+-------------+
| 1  | localhost:35142 | payment-service | charge   | charge-POST |
+----+-----------------+-----------------+----------+-------------+
```

Finally, we can run a test against the mock with a checkout test that has been pre-defined:

```bash
skyramp tester start checkout-test --address localhost:35142
```
You will see that the test scenario passes because the mock payment service is in place and the dependency for the checkout functions as expected. If you want to see the test fail by not having the mock in place, you can delete the running mocks and try the test again:

```bash
skyramp mocker delete -a localhost:35142  
```

You are free to experiment with this scenario to introduce new configurations and then adapt them to your own environment.

This simple example demonstrates how quickly you can set up a mock for your microservice dependencies using Skyramp. For more information, including advanced features of Mocker like [gRPC Proxying](https://skyramp.dev/docs/docker/mocker/mock-description/#grpc-proxying) and [Dynamic Responses](https://skyramp.dev/docs/docker/mocker/mock-description/#dynamic-responses), be sure to visit the [Skyramp Docs](https://skyramp.dev/docs/docker/mocker/).

## Open Swim

In conclusion, Skyramp provides a robust solution for mocking microservice dependencies, offering flexibility, ease of use, and support for various environments and protocols. Whether you are generating mocks from API definitions or creating them from scratch, Skyramp empowers you to streamline your development and testing processes. 

We encourage you to please join the [Skyramp Community Discord](https://discord.gg/qBnEZM6JTb) for any questions, comments, or feedback. 

Happy mocking!