Skip to content
This repository has been archived by the owner on Aug 4, 2023. It is now read-only.

Get mock values from schema.example (if no default value) #304

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

farrago
Copy link

@farrago farrago commented Nov 20, 2015

You may not want to define a default value for a schema object, but still want to provide representative examples, particularly in mock responses.

This is particularly important where string type uses a pattern that doesn't match the hard-coded mock values, which in turns causes the mocked response to fail the response validator. This change allows mock values to be pulled from the example field to solve this problem.

example is inserted between default and enum, leaving the the mock value source precedence as:

  1. 1.2 defaultValue
  2. 2.0 default
  3. 2.0 example
  4. enum (first value)
  5. hardcoded value (or now for date/date-time)

Test plan:

  • Added unit tests to cover the appropriate selection of default and example as the mock value for string, number, integer, and boolean types.
  • Used gulp to run lint and all unit tests and ensured everything passes.
  • Used coverage report to verify all new lines were tested at least once.

Example use case:

Schema is

...
"definitions": {
  "alpha": {
      "description": "Text with only ascii letters",
      "type": "string",
      "pattern": "^([A-Za-z]*)$",
      "example": "SomeTextWithOnlyAsciiLetters"
    },
}
...

Before this change, the mock response would be "Sample Text" which would then fail the response validator as it has a space (which isn't allowed according to the pattern).
After the change, the mock response would be "SomeTextWithOnlyAsciiLetters", which is a valid response.

Caveats

  • This change doesn't fix all such issues. In particular it doesn't use example fields higher up the chain (e.g. object types, or whole responses). This would require more extensive rework of how mock values are created.
  • This change doesn't attempt to validate the example value. This was suggested as a requirement in Finish first pass at enhanced swagger-router mock mode #30 by @whitlockjc. My assumption in this change is that examples are valid values or can be made so.

Alternative options

If this is not a good use of the example field, an alternative, and equally simple, option might be to us a custom x-mock-value parameter (or similar) to get the value from.

In many cases you don't want to define a `default` value for a schema
object, but you still want to provide representative examples,
particularly in mock responses.

This is particularly important where `string` type uses a `pattern` that
doesn't match the hard-coded mock values, which in turns causes the
mocked response to fail the response validator. This change allows mock
values to be pulled from the `example` field to solve this problem.

`example` is inserted between `default` and `enum`, leaving the the
mock value source precedence as:
1. `1.2` `defaultValue`
2. `2.0` `default`
3. `2.0` `example`
4. `enum` (first value)
5. hardcoded value (or *now* for date/date-time)

Test plan:
* Added unit tests to cover the appropriate selection of `default` and `example` as the mock value for string, number, integer, and boolean types.
* Used gulp to run lint and all unit tests and ensured everything passes.
* Used coverage report to verify all new lines were tested at least once.
The previous code always generated 1 item in the array.  If the property
has a minItems value that is >1 then the mock will fail response validation.

This change fixes it by generating the minimum number of items in the
array to match minItems.  If minItems is not defined, then it will
continue to generate 1 item as before.

Test plan:
* Added unit tests to cover minItems set and not set
* Used gulp to run lint and all unit tests and ensured everything passes.
* Used coverage report to verify all new lines were tested at least once.
@farrago
Copy link
Author

farrago commented Nov 23, 2015

I've update this pull request to include generating mock arrays with multiple items to satisfy any minItems specification

@whitlockjc
Copy link
Member

Sorry for the delayed response. Mock values use to work this way but examples and mocks are not the same thing. Since the example values are just text and do not pass through validation, just blindly sending an example as a mock does not make as much sense to me. I'd love to hear what @webron thinks.

@webron
Copy link

webron commented Jan 11, 2016

@whitlockjc if I understand correctly, this is the example field from the schema definition itself, not the examples field in the Response Object. I think it's ok to use it for mocking, whether validated or not. Not sure how much you want to handle user errors.

@farrago
Copy link
Author

farrago commented Jan 12, 2016

@webron yes, this is the example field from the schema definition, and not any higher level fields.

@whitlockjc do you mean schema validation on init, or response validation by the swaggerValidator middleware? The values do go through the latter, and any examples that don't comply with the schema will cause the response validation to fail in the standard way.

I think this is ok because the swagger spec says (my emphasis):

Field Name Type Description
example Any A free-form property to include a an example of an instance for this schema.

Thus it appears that is supposed to be an example of an instance (rather than a general explanatory field), and thus should comply with the format of that schema. That's my interpretation though, and the spec doesn't use MUST or SHOULD (or MUST NOT for that matter), so it doesn't seem 100% guaranteed.

Let me know your thoughts and, as mentioned above, I could change to use something like x-mock-value or similar if it made more sense.

@imZack
Copy link

imZack commented Jan 26, 2016

Any updates? I'm looking for this for a while! @farrago thanks for your work, really helps! 👍

@farrago
Copy link
Author

farrago commented Jan 26, 2016

@imZack, array and object mock values are built by recursing into them and calling getMockValue() for each individual member of the array or object. So they get built up from the defaults/examples of their members rather than from an overall default/example. For my use-case that was exactly what I wanted, so I didn't look in any more detail about where you can define defaults or examples for arrays and objects.

@imZack
Copy link

imZack commented Jan 26, 2016

@farrago thanks for your fast replying, I have noticed that they are built by recurring too. In my case, I want to use fixed mock data just like apiblueprint's response section and I have tried modified array, object to use schema.example, too. It works.

Anyway, if there is a better way to do some kind of fixed mock data way please let me know. Thanks!

@timgent
Copy link

timgent commented Mar 11, 2016

+1 this would be really helpful for us too!

@shri046
Copy link

shri046 commented Feb 9, 2017

+1 this is a very nice feature to have for us too. One suggestion however, the example value should take precedence over default values. Meaning if the schema includes valid values for both example and default, the example value should be displayed. The current PR prefers default value over the example set.

@farrago
Copy link
Author

farrago commented Feb 14, 2017

@shri046, I preferred default over example so that the behaviour would remain the same for anyone who already had both default and example in their definitions, and was thus getting the default as their mock data. Changing the order of precedence would be a breaking change for those users, and would need more convincing.

@robertlevy
Copy link

any movement on this?

@Muldec
Copy link

Muldec commented Nov 29, 2018

I totally agree with @shri046. default should be used when nothing else is provided, thus example must have precedence over default.

In the meantime, is this PR scheduled to be merge any time soon ?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants