Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
    Eric Deandrea
    @edeandrea
    Thanks @mduesterhoeft I totally agree. What I’m trying to figure out is what is the best way to only have to write it once :) I’d hate to write it as an OpenAPI/RAML spec and then have to do it again in my RestDocs spec, and then try and keep them in sync. Trying to pick people’s brains about what they are doing in the space so that we truly only have to write things once.
    Mathias Düsterhöft
    @mduesterhoeft
    @edeandrea no of course you would not write your specification twice. What I wanted to say is that there are different approaches:
    • design first - write your API spec up front - maybe using tools such as stoplight.io - that you implement the API. To make sure the implementation follows your specification you can use tools such as swagger-request-validator
    • test-driven - you describe and introspect your API in your test using spring-restdocs - you can use the extension restdocs-api-spec to also generate an openAPI specification for your API - so you rather generate the specification from the knowledge you put into your testt
    Jakub Kubryński
    @jkubrynski
    Hi! Is there any particular reason that HalLinkExtractor does not support links on embedded resources?
    Andy Wilkinson
    @wilkinsona
    IIRC, my reasoning was that the links should be documented for the resource in its main usage so having to document them again in an embedded usage would be unnecessary
    Jakub Kubryński
    @jkubrynski
    But if you document fields of embedded documents it'd be probably also good to not skip the links?
    Andy Wilkinson
    @wilkinsona
    I wouldn't document the fields either. You'll end up with lots of repetition.
    Jakub Kubryński
    @jkubrynski
    OK. I'll review if just linking to other parts of the documentation will be nice
    Jakub Kubryński
    @jkubrynski
    Is it possible to set the default value for the attribute? I want to use custom attribute that will be available only on few fields
    Andy Wilkinson
    @wilkinsona
    @jkubrynski There are a few options discussed in spring-projects/spring-restdocs#291
    Knut Schleßelmann
    @kschlesselmann
    Did anyone here ever setup RestDocs using kotlin and WebTestClient using JUnit5? I cannot get a running setup here :-(
    Andy Wilkinson
    @wilkinsona
    What's the problem?
    Knut Schleßelmann
    @kschlesselmann
    @wilkinsona org.junit.jupiter.api.extension.ParameterResolutionException: Failed to resolve parameter [org.springframework.web.context.WebApplicationContext webApplicationContext] using
    @ExtendWith(RestDocumentationExtension::class, SpringExtension::class)
    internal class DocTest {
    
        private var webTestClient: WebTestClient = WebTestClient.bindToServer().build()
    
        @BeforeEach
        fun setUp(webApplicationContext: WebApplicationContext , restDocumentation: RestDocumentationContextProvider) {
            this.webTestClient = WebTestClient.bindToApplicationContext(webApplicationContext)
                    .configureClient()
                    .filter(documentationConfiguration(restDocumentation))
                    .build()
        }
    
        @Test
        fun stuff() {
            this.webTestClient.get().uri("/").accept(MediaType.APPLICATION_JSON)
                    .exchange().expectStatus().isOk
                    .expectBody().consumeWith(document("index"))
        }
    }
    Would be even better to have some constructor injection setup so that webTestClient could be val
    ```
    @SpringBootTest
    @ActiveProfiles("test")
    @ExtendWith(RestDocumentationExtension::class, SpringExtension::class)
    internal class DocTest {
    doesn't help either
    Or even better: Have @AutoconfigureRestDocs working in webflux
    Andy Wilkinson
    @wilkinsona
    The injection of the WebApplicationContext doesn't have anything to do with REST Docs as it's not involved with that
    I assume that Spring Framework's JUnit 5 integration allows the application context to be injected like that, but I don't know for sure. You'll need some configuration that creates such an application context and I can't see any sign of that in your first example.
    Knut Schleßelmann
    @kschlesselmann
    @wilkinsona Shouldn't the seconad example have a context through @SpringBootTest?
    Knut Schleßelmann
    @kschlesselmann
    @wilkinsona I changed my definition to applicationContext: ApplicationContext and it works :-S
    Knut Schleßelmann
    @kschlesselmann
    Anyone an idea why my base url is still localhost:8080 if I use the following to bootstrap my RestDocs tests
    @SpringBootTest
    @ActiveProfiles("test")
    @ExtendWith(RestDocumentationExtension::class, SpringExtension::class)
    internal abstract class AbstractRestDocsTest {
    
        protected var webTestClient: WebTestClient = WebTestClient.bindToServer().build()
    
        @BeforeEach
        fun setUp(applicationContext: ApplicationContext, restDocumentation: RestDocumentationContextProvider) {
            webTestClient = WebTestClient.bindToApplicationContext(applicationContext)
                    .configureClient()
                    .baseUrl("https://${applicationContext.applicationName}.example.com")
                    .filter(documentationConfiguration(restDocumentation)
                            .operationPreprocessors()
                            .withRequestDefaults(prettyPrint())
                            .withResponseDefaults(prettyPrint()))
                    .build()
        }
    }
    Andy Wilkinson
    @wilkinsona
    Why are you creating it twice, once bound to a server and once bound to the application context?
    Knut Schleßelmann
    @kschlesselmann
    @wilkinsona So I can use var without null. Some kind of constructor injection would be nice … or @AutoConfigureRestDocs for WebTestClient :-)
    But does it matter since I override the instance later on?
    Andy Wilkinson
    @wilkinsona
    @AutoConfigureRestDocs already works with WebTestClient
    The duplicate configuration of WebTestClient matters in this context as it makes it harder to figure out what you're doing and why.
    Andy Wilkinson
    @wilkinsona
    Looks like we missed a doc update as part of https://github.com/spring-projects/spring-boot/pull/10969/. It's been supported since 2.0
    Knut Schleßelmann
    @kschlesselmann
    Good to know … never tried since it was missing in the docs :-)
    @wilkinsona So how would for example pretty print work with WebTestClient If I use @AutoConfigureRestDocs?
    Andy Wilkinson
    @wilkinsona
    You'd set it up with a RestDocsWebTestClientConfigurationCustomizer
    Knut Schleßelmann
    @kschlesselmann
    OK, let me try :-) @wilkinsona awesome work btw :thumbsup:
    Knut Schleßelmann
    @kschlesselmann

    @wilkinsona Works like a charm :-) The base url is still a problem though. I tried

    @TestConfiguration
    internal class RestDocsConfiguration : RestDocsWebTestClientConfigurationCustomizer {
    
        override fun customize(configurer: WebTestClientRestDocumentationConfigurer) {
            configurer.operationPreprocessors()
                    .withRequestDefaults(prettyPrint())
                    .withResponseDefaults(prettyPrint())
        }
    
        @Bean
        fun webTestClientBuilderCustomizer() = WebTestClientBuilderCustomizer {
            it
                    .baseUrl("https://fooo.bar")
        }
    }

    Pretty print is applied as expected … my snippets still refer to localhost:8080. Would those cusomizers be picked up by

    @SpringBootTest
    @ActiveProfiles("test")
    @AutoConfigureRestDocs
    @AutoConfigureWebTestClient
    @Import(RestDocsConfiguration::class)
    @ExtendWith(RestDocumentationExtension::class, SpringExtension::class)
    internal abstract class AbstractRestDocsTest {
    
        @Autowired
        protected lateinit var webTestClient: WebTestClient
    }

    at all?

    Andy Wilkinson
    @wilkinsona
    A WebTestClientBuilderCustomizer not being picked up sounds very similar to spring-projects/spring-boot#15132
    Knut Schleßelmann
    @kschlesselmann
    Yeah … let's see how this turns out
    Thanks again
    Knut Schleßelmann
    @kschlesselmann
    Can you somehow propagate the .optional() information to the generated snippets? For example ${parameterName} (optional) in the first column of the table?
    Andy Wilkinson
    @wilkinsona
    Yes. The value of optional is already included in the model. If you want it to appear in the generated snippets, you can provide a custom template and use {{optional}}
    Christopher Kocel
    @kkocel
    Hello, I have a question - is there a possibility to add path to base url that will mask (localhost:8080) ?
    wykaPedia
    @wykapedia
    @kkocel yes, you can use the URI configurer to achieve this:
    
    
    
    
    this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
            .apply(documentationConfiguration(this.restDocumentation).uris()
                    .withScheme("https")
                    .withHost("example.com")
                    .withPort(443))
            .build();
    Gabriel Claudiu Georgiu
    @ClaudiuGeorgiu

    Hello, is it possible to generate both markdown and asciidoc snippets at the same time? I tried with the following code but it doesn't work like I would like (only markdown/asciidoc documentation gets generated but not both at the same time).

    this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
                    .apply(documentationConfiguration(this.restDocumentation)
                            .snippets().withTemplateFormat(TemplateFormats.asciidoctor()).and()
                            .snippets().withTemplateFormat(TemplateFormats.markdown()))
                    .build();

    Thanks in advance.

    Andy Wilkinson
    @wilkinsona

    @ClaudiuGeorgiu I haven't heard of that requirement before, but I think it might be possible if you apply REST Docs twice when you're building the MockMvc instance. Something like this:

    MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
            .apply(documentationConfiguration(this.restDocumentation).snippets()
                    .withTemplateFormat(TemplateFormats.asciidoctor()))
            .apply(documentationConfiguration(this.restDocumentation).snippets()
                    .withTemplateFormat(TemplateFormats.markdown()))
            .build();

    I think that's worth a try, although it may break in unexpected ways as I don't think it's been tried before.

    Gabriel Claudiu Georgiu
    @ClaudiuGeorgiu
    @wilkinsona Thank you, I have tried your suggestion but unfortunately it doesn't work: the second apply(...) overrides the first one, so I'm only getting markdown documentation (or asciidoc, if I swap the instructions). My use case is the following: I'm using swagger2markup to generate the documentation and REST Docs to generate the code snippets; I want to generate the markdown documentation to be used as a README in the repository, while the asciidoc documentation is needed to generate the final pdf/html. For now I have 2 options:
    • generate everything in asciidoc and then convert it to markdown (I would prefer to avoid this solution since both swagger2markup and REST Docs support markdown output)
    • run the tests twice, once using asciidoc as output and the second time using markdown (I would like to avoid this as well since it adds unnecessary overhead)
    Andy Wilkinson
    @wilkinsona

    Ah, yeah. Of course. That won't stop the attribute from the request that holds the configuration from being overwritten. Ok. I think you can stop that from happening if you do something like this:

    DefaultMockMvcBuilder builder = MockMvcBuilders.webAppContextSetup(this.context);
    RequestPostProcessor asciidoc = documentationConfiguration(this.restDocumentation)
            .snippets().withTemplateFormat(TemplateFormats.asciidoctor())
            .beforeMockMvcCreated(builder, this.context);
    RequestPostProcessor markdown = documentationConfiguration(this.restDocumentation)
            .snippets().withTemplateFormat(TemplateFormats.markdown())
            .beforeMockMvcCreated(builder, this.context);
    MockMvc mockMvc = builder.build();
    mockMvc.perform(get("/").accept(MediaType.APPLICATION_JSON))
            .andExpect(status().isOk()).andDo((result) -> {
                asciidoc.postProcessRequest(result.getRequest());
                document("asciidoc-and-markdown").handle(result);
                markdown.postProcessRequest(result.getRequest());
                document("asciidoc-and-markdown").handle(result);
            });

    That seems to work fine for the default snippets anyway. It's undoubtedly a bit of a hack, though. REST Docs hasn't been designed to document the same thing twice.

    Gabriel Claudiu Georgiu
    @ClaudiuGeorgiu
    Thank you @wilkinsona, it works.
    Arun Kumar
    @arumaum
    Hi All , Is there way to customize AutoDocumentation.requestFields() Request field few of the fields need to deleted from api doc but it is required for other purpose how we can achieve