Docsright arrowBlackbirdright arrowCreating Mock Instances with Blackbird

8 min • read

Creating Mock Instances with Blackbird

Mocking API Endpoints enhances productivity, facilitates testing and improves the overall quality of the application. Quickly spin up a mocking instance that enables parallel development of frontend and backend components by allowing developers to work on their respective parts simultaneously.

If you have your own examples included in your OpenAPI specification, you can use those as well by passing in the Prefer: dynamic=false header to requests to your mock API server.

Deploying a new Mock API requires the use of OpenAPI Specification Version.

Create a new Mock

If you have an existing API Service in our API catalog, you can use its slug name to spin up a new mock server. You can learn more about creating a new API in the Blackbird catalog here.

Alternatively, you can download the sample petstore.yaml file to test with or use your own.

Update an existing Mock

To update a running mock, you can reference an existing API service by using its name.

Alternatively, you can upload a new API spec to replace the existing one.

Delete a Mock

To delete a running mock, you can run the mock delete command to remove it.

List Mocks

To see a list of all active mocks, you can run the list deployments command.

Secure a Mock

By default the mock endpoints are available to the public. In order to secure these endpoints we can use APIKeys. We can also create and set an APIKey on creation with the --apikey-header flag.

Configure a Mock

After creating a mock, you can dynamically adjust it's configuration by using the mock config <mock-name> set command.

To preview the configuration of your mock instance, you can use the mock config <mock-name> get command.

At the moment, dynamic is the only configuration value that can be set.

Set dynamic data generation

Your mock instance will have a default configuration that will generate random data based on the schema objects defined in the OpenAPI specification. If you have examples defined throughout your OpenAPI specification, you might want to disable the dynamic data generation.

Troubleshooting

Unable to enforce a specific error response

In order to enforce a specific error response, you need to specify the Prefer header with a respective code value.

This would make our mock server prefer a 404 error response from the list of responses defined in the OpenAPI specification.

Mock Server does not use my examples

By default, the mock server will return dynamic data generated based on the Schema Objects defined in the OpenAPI specification. If you have your own examples included in your OpenAPI specification, you can use those as well by passing in the Prefer: dynamic=false header to requests to your mock server.

You can also combine it with the Prefer: code header to enforce a specific error response.

Mock Server returning unexpected data / objects with weird properties

If you are seeing unexpected data or objects with weird properties, it is likely your OpenAPI definition is not imposing restrictions on the data.

In this example, the schema defines an object with a required name property that is to be a string, but it does not restrict any other properties. As such, the mock server is free to return any object that has a name property that is a string, but may also have other properties.

In Schema Objects, regardless of the version of the OpenAPI, there is a keyword called additionalProperties that can be used to define the behavior of unspecified properties.

This schema will only accept objects that have a name property that is a string and no other properties. You can also specify a different Schema Object if you do expect extra properties, i.e. if you want to have a dictionary.

This schema will only accept objects that have a name property that is a string and any other properties that are strings.

Bear in mind that this may have implications if you reference this schema in other parts of your OpenAPI definition. Since there is no notion of inheritance in Schema Objects, you may have to copy the schema or adjust the "base" schema to accommodate the new restrictions.

That is particularly common if you have a "base" schema that you try to combine with others using "allOf".

The above schema is semantically wrong and will always evaluate to false regardless of the input provided. That is because each child schema in allOf is applied in isolation against the piece of input.

Say we have this input:

Now, if we take the "User" schema and apply it to the input, it will evaluate to false, since "age" is not expected to be there. If we take the second schema and apply it to the input, it will also evaluate to false, since "name" is not expected to be there.

If you do not want to copy the schema, you can try extending the "base" schema.

While the above slightly changes the behavior of the User schema, the root schema now correctly evaluates to true for the input provided, while disallowing any extra properties.

There is a better aid to that in OpenAPI 3.1.0, assuming you use the json schema dialect 2019-09 or newer, namely unevaluatedProperties to enforce that no properties are allowed that are not defined in the schema.

My payload seems correct, but I'm getting 422

Make sure your Schema Objects are defined correctly. As already mentioned in a few previous examples, our definition may seem correct, but gets evaluated to false when the mock server tries to validate it. While it is not feasible to list all possible instances where this might happen, here is a list of a few examples:

The above Schema is quite open-ended, and the range of compliant inputs is very narrow. This is because oneOf acts as a logical XOR operator, meaning the input must match exactly one of the schemas. That on its own is not an issue, but usually when the sub schemas themselves are restrictive, which is not the case here. The first schema accepts any object as long as its name property is of a string. In practice, the only invalid input would be an object with a name property that is not a string.

The second schema is no different - the only invalid input would be an object with an age property that is not a number.

As one sees, there's a large set of overlapping data, and as such it is easy to author an invalid input.


Another common issue is when allOf is used to "combine" schemas. In practice, allOf acts as a logical AND operator, meaning the input must match all child schemas. It does not extend or inherit the schema that is referenced, not does it override any constraints the referenced schema introduces.

For more details on specific errors that you might encounter when mocking, please take a look at the Mock Server Errors reference page.