Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Creating expectations from OpenAPI without components section #1867

Open
ahasbini opened this issue Apr 28, 2024 · 0 comments
Open

Creating expectations from OpenAPI without components section #1867

ahasbini opened this issue Apr 28, 2024 · 0 comments

Comments

@ahasbini
Copy link

ahasbini commented Apr 28, 2024

Describe the issue
Loading an openapi spec will throw a NullPointerException if the spec:

  • Has at least one response with content (json response or similar) for a path.
  • And does not have component section

An openapi spec without component section is valid, but mockserver fails to handle this case.

What you are trying to do
Creating expectations from an openapi YAML file.

MockServer version
mockserver-netty-5.14.0-shaded.jar

To Reproduce
Steps to reproduce the issue:

  1. Examples files:
example-without-components.yaml
openapi: 3.0.0
info:
  title: 'Mockserver Component Test'
  version: 0.0.1

servers:
  - url: 'http://api.example.com/'

paths:
  /pets:
    get:
      summary: List all pets
      operationId: listPets
      tags:
        - pets
      parameters:
        - name: limit
          in: query
          description: How many items to return at one time (max 100)
          required: false
          schema:
            type: integer
            maximum: 100
            format: int32
      responses:
        '200':
          description: A paged array of pets
          headers:
            x-next:
              description: A link to the next page of responses
              schema:
                type: string
          content:
            application/json:
              schema:
                type: array
                maxItems: 100
                items:
                  type: object
                  required:
                    - id
                    - name
                  properties:
                    id:
                      type: integer
                      format: int64
                    name:
                      type: string
                    tag:
                      type: string
    post:
      summary: Create a pet
      operationId: createPets
      tags:
        - pets
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
                - id
                - name
              properties:
                id:
                  type: integer
                  format: int64
                name:
                  type: string
                tag:
                  type: string
        required: true
      responses:
        '201':
          description: Null response
example-with-components.yaml
openapi: 3.0.0
info:
  title: 'Mockserver Component Test'
  version: 0.0.1

servers:
  - url: 'http://api.example.com/'

paths:
  /pets:
    get:
      summary: List all pets
      operationId: listPets
      tags:
        - pets
      parameters:
        - name: limit
          in: query
          description: How many items to return at one time (max 100)
          required: false
          schema:
            type: integer
            maximum: 100
            format: int32
      responses:
        '200':
          description: A paged array of pets
          headers:
            x-next:
              description: A link to the next page of responses
              schema:
                type: string
          content:
            application/json:
              schema:
                type: array
                maxItems: 100
                items:
                  type: object
                  required:
                    - id
                    - name
                  properties:
                    id:
                      type: integer
                      format: int64
                    name:
                      type: string
                    tag:
                      type: string
    post:
      summary: Create a pet
      operationId: createPets
      tags:
        - pets
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
                - id
                - name
              properties:
                id:
                  type: integer
                  format: int64
                name:
                  type: string
                tag:
                  type: string
        required: true
      responses:
        '201':
          description: Null response
components:
  schemas:
    Empty:
      type: string
  1. Start the mockserver (on Windows, note: slf4j-simple-1.7.36.jar needs to be placed in same folder with yaml files and mockserver jar file):
java .;slf4j-simple-1.7.36.jar;mockserver-netty-5.14.0-shaded.jar org.mockserver.cli.Main -serverPort 1080 -logLevel INFO
  1. Create expectations using yam file (from classpath):
curl -v -X PUT "http://localhost:1080/mockserver/openapi" -d'{
    "specUrlOrPayload": "example-without-components.yaml"
}'

OR

curl -v -X PUT "http://localhost:1080/mockserver/openapi" -d'{
    "specUrlOrPayload": "example-with-components.yaml"
}'

Expected behaviour

With example-with-components.yaml
[MockServer-EventLog0] INFO org.mockserver.log.MockServerEventLog - 1080 started on port: 1080
[MockServer-EventLog0] INFO org.mockserver.log.MockServerEventLog - 1080 creating expectation:

  {
    "httpRequest" : {
      "operationId" : "listPets",
      "specUrlOrPayload" : "example-with-components.yaml"
    },
    "httpResponse" : {
      "statusCode" : 200,
      "headers" : {
        "x-next" : [ "some_string_value" ],
        "content-type" : [ "application/json" ]
      },
      "body" : [ {
        "id" : 0,
        "name" : "some_string_value",
        "tag" : "some_string_value"
      } ]
    },
    "id" : "ffffffff-ecef-6ecc-ffff-ffffecef6ecc",
    "priority" : 0,
    "timeToLive" : {
      "unlimited" : true
    },
    "times" : {
      "unlimited" : true
    }
  }

 with id:

  ffffffff-ecef-6ecc-ffff-ffffecef6ecc

[MockServer-EventLog0] INFO org.mockserver.log.MockServerEventLog - 1080 creating expectation:

  {
    "httpRequest" : {
      "operationId" : "createPets",
      "specUrlOrPayload" : "example-mockserver-with-components.yaml"
    },
    "httpResponse" : {
      "statusCode" : 201
    },
    "id" : "ffffffff-d9de-dd98-ffff-ffffd9dedd98",
    "priority" : 0,
    "timeToLive" : {
      "unlimited" : true
    },
    "times" : {
      "unlimited" : true
    }
  }

 with id:

  ffffffff-d9de-dd98-ffff-ffffd9dedd98

MockServer Log

With example-without-components.yaml
[MockServer-EventLog0] INFO org.mockserver.log.MockServerEventLog - 1080 started on port: 1080
[MockServer-EventLog0] ERROR org.mockserver.log.MockServerEventLog - 1080 exception processing {
  "method" : "PUT",
  "path" : "/mockserver/openapi",
  "headers" : {
    "content-length" : [ "53" ],
    "content-encoding" : [ ".*" ],
    "User-Agent" : [ "curl/7.88.1" ],
    "Host" : [ "localhost:1080" ],
    "Content-Type" : [ "application/x-www-form-urlencoded" ],
    "Accept" : [ "*/*" ]
  },
  "keepAlive" : true,
  "secure" : false,
  "localAddress" : "localhost/127.0.0.1:1080",
  "remoteAddress" : "127.0.0.1",
  "body" : {
    "type" : "STRING",
    "string" : "{\n    \"specUrlOrPayload\": \"example-without-components.yaml\"\n}",
    "contentType" : "application/x-www-form-urlencoded"
  }
}
java.lang.NullPointerException
        at org.mockserver.openapi.OpenAPIConverter.lambda$null$6(OpenAPIConverter.java:85)
        at java.util.Iterator.forEachRemaining(Iterator.java:116)
        at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
        at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
        at org.mockserver.openapi.OpenAPIConverter.lambda$null$7(OpenAPIConverter.java:79)
        at java.util.Optional.ifPresent(Optional.java:159)
        at org.mockserver.openapi.OpenAPIConverter.lambda$buildHttpResponse$11(OpenAPIConverter.java:78)
        at java.util.Optional.ifPresent(Optional.java:159)
        at org.mockserver.openapi.OpenAPIConverter.buildHttpResponse(OpenAPIConverter.java:70)
        at org.mockserver.openapi.OpenAPIConverter.lambda$buildExpectations$2(OpenAPIConverter.java:52)
        at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
        at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
        at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1374)
        at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
        at java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:270)
        at java.util.Iterator.forEachRemaining(Iterator.java:116)
        at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
        at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
        at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
        at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
        at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
        at org.mockserver.openapi.OpenAPIConverter.buildExpectations(OpenAPIConverter.java:62)
        at org.mockserver.mock.HttpState.add(HttpState.java:247)
        at org.mockserver.mock.HttpState.handle(HttpState.java:618)
        at org.mockserver.netty.HttpRequestHandler.channelRead0(HttpRequestHandler.java:96)
        at org.mockserver.netty.HttpRequestHandler.channelRead0(HttpRequestHandler.java:48)
        at shaded_package.io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99)
        at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
        at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
        at shaded_package.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
        at shaded_package.io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436)
        at shaded_package.io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
        at shaded_package.io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251)
        at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
        at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
        at shaded_package.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
        at org.mockserver.dashboard.DashboardWebSocketHandler.channelRead(DashboardWebSocketHandler.java:137)
        at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
        at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
        at shaded_package.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
        at org.mockserver.netty.websocketregistry.CallbackWebSocketServerHandler.channelRead(CallbackWebSocketServerHandler.java:57)
        at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
        at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
        at shaded_package.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
        at shaded_package.io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
        at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
        at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
        at shaded_package.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
        at shaded_package.io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
        at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
        at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
        at shaded_package.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
        at shaded_package.io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
        at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
        at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
        at shaded_package.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
        at shaded_package.io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436)
        at shaded_package.io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:327)
        at shaded_package.io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:299)
        at shaded_package.io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251)
        at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
        at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
        at shaded_package.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
        at org.mockserver.netty.unification.PortUnificationHandler.switchToHttp(PortUnificationHandler.java:279)
        at org.mockserver.netty.unification.PortUnificationHandler.decode(PortUnificationHandler.java:153)
        at shaded_package.io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:510)
        at shaded_package.io.netty.handler.codec.ReplayingDecoder.callDecode(ReplayingDecoder.java:366)
        at shaded_package.io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:279)
        at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
        at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
        at shaded_package.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
        at shaded_package.io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
        at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
        at shaded_package.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
        at shaded_package.io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
        at shaded_package.io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
        at shaded_package.io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:722)
        at shaded_package.io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:658)
        at shaded_package.io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:584)
        at shaded_package.io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496)
        at shaded_package.io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
        at shaded_package.io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
        at java.lang.Thread.run(Thread.java:745)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant