-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Open
Description
Describe the issue
The mock server should return the right expectation even if i use a header like Accept-Language that is describe from openApi
What you are trying to do
I have an OpenApi specifying header
"components": {
"parameters": {
"LanguageV1": {
"in": "header",
"name": "Accept-Language",
"schema": {
"type": "string",
"minLength": 5,
"maxLength": 5,
"examples": [
"fr-FR",
"en-EN"
]
},
"required": true
},
Then i send http request to the mock server like this :
curl -X 'POST' \
'http://172.23.0.14:1080/v1/my-route' \
-H 'Accept-Language: fr-FR' \
-H 'Content-Type: application/json' \
-d '{
"level": "log",
"message": "User completed step 1 of process"
}'
I expect a match from the mock server, but it fails to use the right expectation because of this :
method matched
path matched
body matched
headers didn't match:
schema match failed expect:
{
"format" : "string",
"maxLength" : 5,
"minLength" : 5
}
found:
fr-FR
errors:
JsonParseException - Unrecognized token 'fr': was expecting (JSON String, Number (or 'NaN'/'INF'/'+INF'), Array, Object or token 'null', 'true' or 'false')
at [Source: (String)"fr-FR"; line: 1, column: 3]
multimap matching key match failed for key:
Accept-Language
multimap match failed expected:
{
"keyMatchStyle" : "MATCHING_KEY",
"Accept-Language" : {
"parameterStyle" : "SIMPLE",
"values" : [ {
"schema" : {
"format" : "string",
"maxLength" : 5,
"minLength" : 5
}
} ]
}
}
found:
{
"Content-Type" : [ "application/json" ],
"Content-Length" : [ "72" ],
"Connection" : [ "keep-alive" ],
"Accept-Language" : [ "fr-FR" ]
}
failed because:
multimap values don't match
MockServer version
5.15.0
To Reproduce
Steps to reproduce the issue:
Juste add the LanguageV1 component and use it inside your own paths from an OpenApi
- How you are running MockServer (i.e maven plugin, docker, etc) : i use Javascript server
- Code you used to create expectations
import mockserver from 'mockserver-node'
import { mockServerClient } from 'mockserver-client'
import { overrideMockServer } from './overrides/override-mock-server.js'
import express from 'express'
import swaggerUi from 'swagger-ui-express'
import fs from 'fs'
import path from 'path'
import { fileURLToPath } from 'url'
const mockServerUrl = 'http://172.23.0.14';
const openAPIFilePath = '../open-api/openapi.json';
const appPort = 1080;
const swaggerUiExpressAppPort = '1081';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const clientMockServer = await startMockServer();
await startSwaggerUIExpressApp(clientMockServer);
async function startMockServer() {
await mockserver.stop_mockserver({ serverPort: appPort }
);
await mockserver.start_mockserver({
serverPort: appPort,
verbose: true,
jvmOptions: [
'-Dmockserver.enableCORSForAllResponses=true',
'-Dmockserver.corsAllowOrigins="*"',
'-Dmockserver.corsAllowMethods="CONNECT, DELETE, GET, HEAD, OPTIONS, POST, PUT, PATCH, TRACE"',
'-Dmockserver.corsAllowHeaders="Allow, Content-Encoding, Content-Length, Content-Type, ETag, Expires, Last-Modified, Location, Server, Vary, Authorization"',
'-Dmockserver.corsAllowCredentials=true',
],
});
console.log(`MockServer started on port ${appPort}`)
const client = await mockServerClient('localhost', appPort)
// Read and modify the OpenAPI specification to fix the Accept-Language header issue
let openApiSpec = JSON.parse(fs.readFileSync(path.join(__dirname, openAPIFilePath), 'utf8'))
// Use the modified OpenAPI specification
await client.openAPIExpectation({ specUrlOrPayload: openApiSpec })
await overrideMockServer(client);
return client;
}
async function startSwaggerUIExpressApp(clientMockServer) {
const expressApp = express();
let openApiSpecification = JSON.parse(fs.readFileSync(path.join(__dirname, openAPIFilePath), 'utf8'));
openApiSpecification = await enhanceOpenAPISpecificationWithMockServerOverrides(clientMockServer, openApiSpecification);
openApiSpecification.servers = [
{
url: `${mockServerUrl}:${appPort}`, // URL of your mock server
description: 'Mock Server',
},
];
expressApp.use('/api-docs', swaggerUi.serve, swaggerUi.setup(openApiSpecification));
expressApp.listen(swaggerUiExpressAppPort, () => {
console.log(`Swagger UI is available at ${mockServerUrl}:${swaggerUiExpressAppPort}/api-docs`);
});
}
async function enhanceOpenAPISpecificationWithMockServerOverrides(clientMockServer, openApiSpec) {
try {
const expectations = await clientMockServer.retrieveActiveExpectations({});
expectations.forEach((expectation) => {
if (expectation.httpRequest.specUrlOrPayload !== openAPIFilePath) {
const httpRequest = expectation.httpRequest;
const httpResponse = expectation.httpResponse;
const httpResponseObjectCallback = expectation.httpResponseObjectCallback;
if (!httpRequest || (!httpResponse && !httpResponseObjectCallback)) return;
const path = httpRequest.path;
const method = httpRequest.method.toLowerCase();
if (!openApiSpec.paths[path]) {
openApiSpec.paths[path] = {};
}
if (!openApiSpec.paths[path][method]) {
openApiSpec.paths[path][method] = {
summary: `MockServer expectation for ${method.toUpperCase()} ${path}`,
responses: {},
};
}
if (httpResponse) {
openApiSpec.paths[path][method].responses[httpResponse.statusCode] = {
description: httpResponse.reasonPhrase + ' [Override MockServer]',
content: {
'application/json': {
schema: {
type: 'object',
example: JSON.stringify(httpResponse.body),
},
},
},
};
}
if (httpResponseObjectCallback) {
openApiSpec.paths[path][method].summary = openApiSpec.paths[path][method].summary + ' [Callback MockServer]';
}
openApiSpec.paths[path][method]['x-mockserver-expectation'] = expectation;
}
});
return openApiSpec;
} catch (error) {
console.error('Error fetching MockServer expectations:', error);
return openApiSpec;
}
}
- What error you saw : see above
Expected behaviour
it should return a valid expectation
MockServer Log
Log output, as INFO level (or lower)
Metadata
Metadata
Assignees
Labels
No labels