oliyh / martian

The HTTP abstraction library for Clojure/script, supporting OpenAPI, Swagger, Schema, re-frame and more
MIT License
525 stars 42 forks source link

Exception when generating no content response #183

Open zc2021 opened 10 months ago

zc2021 commented 10 months ago

Hi,

I am getting an illegal argument exception related to Schema when using martian.test/respond-with-generated on an API including a 204 (no content) response.

It looks like this is because the handler response schema has a body value of nil, which cannot be handled by the generator generator.

A minimal example is below. Am I missing something in the API client or test setup?

(let [m (-> (martian-http/bootstrap-openapi "/tmp/martian-test.json") 
            (martian-test/respond-with-generated {:nil-body-response :success}))]
  (martian/response-for m :nil-body-response))
;= Execution error (IllegalArgumentException) at schema.core/eval23004$fn$G (core.clj:110).
;= No implementation of method: :spec of protocol: #'schema.core/Schema found for class: nil

/tmp/martian-test.json

{
    "openapi": "3.0.1",
    "info": {
        "title": "Test Spec",
        "version": "1.0.0"
    },
    "servers": [
      {
        "url": "http://127.0.0.1:80/"
      }
    ],
    "paths": {
        "/nil-body-response": {
            "get": {
                "operationId": "nilBodyResponse",
                "summary": "a test route",
                "responses": {
                    "204": {
                        "description": "an empty response"
                    }
                }
            }
        }
    }
}

Looking at the trace brought me to martian.test/make-generator:

[...
 [clojure.test.check.generators$one_of invoke "generators.cljc" 345]
 [martian.test$make_generator invokeStatic "test.cljc" 24]
 [martian.test$make_generator invoke "test.cljc" 20]
 [martian.test$make_response invokeStatic "test.cljc" 27]
 [martian.test$make_response invoke "test.cljc" 26]
 [martian.test$generate_responses$fn__34929 invoke "test.cljc" 34]
 [tripod.context$try_f invokeStatic "context.cljc" 32]
...]

make-generator takes the response type (:success) and the response schemas from the Martian client. After filtering for responses in the appropriate status range, the filtered responses are mapped with schema-generators.generators/generator.

The relevant response schemas:

(-> (martian-http/bootstrap-openapi "/tmp/martian-test.json")
    (martian-test/respond-with-generated {:nil-body-response :success})
    (martian/handler-for :nil-body-response)
    :response-schemas)
;= [{:status (eq 204), :body nil}]

Calling (schema-generators.generators/generator nil), as happens when generating a body value generator for the response schema above, throws the illegal argument exception:

(schema-generators.generators/generator nil)
 ;= Execution error (IllegalArgumentException) at schema.core/eval23004$fn$G (core.clj:110).
 ;= No implementation of method: :spec of protocol: #'schema.core/Schema found for class: nil

Thanks for your time!

oliyh commented 10 months ago

Hi,

Thanks for the excellent write-up. I think you're right, in that the lack of a body schema is making the generator choke. I will try to find time to address this soon.

Thanks