Dive into Mocking Your Microservice Dependencies with Skyramp

dangross

Dan Gross

Posted on December 14, 2023

Dive into Mocking Your Microservice Dependencies with Skyramp

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 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. Mocker is a solution for creating mock API services which run in-cluster for either Kubernetes or Docker Compose. In the architecture diagram below, you can see how mock descriptions can be applied to the Skyramp Worker to run the mocks.

Image description

Skyramp Clients

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

  1. The command-line interface (CLI) for using Skyramp in a terminal.
  2. The Visual Studio Code extension for using Skyramp in VSCode.
  3. The Skyramp libraries for Python or JavaScript 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 or Protobuf. 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 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 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 on how to configure responses for your mocks.

What's in a Mock?

At a fundamental level, a Skyramp mock consists of an endpoint, a response, and a mock configuration. Below is a sample mock description file as an example. You can read more details about Skyramp mock descriptions in the Skyramp Docs.

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
Enter fullscreen mode Exit fullscreen mode

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. Start by launching the sandbox environment in GitHub Codespaces:

Open in GitHub Codespaces

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

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:

cd skyramp/docker-compose
Enter fullscreen mode Exit fullscreen mode

Next, let's bring up the containers, which include the Skyramp Worker container and the application containers.

docker compose up &
Enter fullscreen mode Exit fullscreen mode

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

Let's apply the mock to the Skyramp Worker:

skyramp mocker apply payment-service-k8s --address localhost:35142
Enter fullscreen mode Exit fullscreen mode

Then, we can verify the mock is running:

skyramp mocker status --address localhost:35142
Enter fullscreen mode Exit fullscreen mode

You should see output like this:

Applied mocks at the address 'localhost:35142': 
+----+-----------------+-----------------+----------+-------------+
| ID | ADDRESS         | SERVICE         | ENDPOINT | METHOD      |
+----+-----------------+-----------------+----------+-------------+
| 1  | localhost:35142 | payment-service | charge   | charge-POST |
+----+-----------------+-----------------+----------+-------------+
Enter fullscreen mode Exit fullscreen mode

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

skyramp tester start checkout-test --address localhost:35142
Enter fullscreen mode Exit fullscreen mode

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:

skyramp mocker delete -a localhost:35142  
Enter fullscreen mode Exit fullscreen mode

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 and Dynamic Responses, be sure to visit the Skyramp Docs.

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 for any questions, comments, or feedback.

Happy mocking!

💖 💪 🙅 🚩
dangross
Dan Gross

Posted on December 14, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related