swagger-tools
swagger-tools copied to clipboard
Get mock values from `schema.example` (if no `default` value)
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.2defaultValue2.0default2.0exampleenum(first value)- hardcoded value (or now for date/date-time)
Test plan:
- Added unit tests to cover the appropriate selection of
defaultandexampleas 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
examplefields higher up the chain (e.g.objecttypes, or wholeresponses). This would require more extensive rework of how mock values are created. - This change doesn't attempt to validate the
examplevalue. This was suggested as a requirement in #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.
I've update this pull request to include generating mock arrays with multiple items to satisfy any minItems specification
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.
@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.
@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.
Any updates? I'm looking for this for a while! @farrago thanks for your work, really helps! :+1:
@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.
@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!
+1 this would be really helpful for us too!
+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.
@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.
any movement on this?
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 ?