spring-projects/spring-restdocs

Adding Context Path in Spring REST Docs with WebTestClient

PremAhankare opened this issue · 8 comments

I'm trying to add a context path (e.g., /my-app) to the requests generated by Spring REST Docs when using WebTestClient. Currently, the generated cURL commands do not include the context path:

$ curl 'http://localhost:4444/accounts/123/dummy' -i -X GET

I would like them to reflect the context path, like this:

$ curl 'http://localhost:4444/my-app/accounts/123/dummy' -i -X GET

How can I achieve this?

Reference

Spring REST Docs Issue #135

Thank you!

I have tried setting the baseUrl to include the context path, but it doesn’t seem to work as expected.

this.webTestClient = WebTestClient.bindToApplicationContext(context).configureClient().baseUrl("http://localhost:4444/my-app")

There's no concept of a context path with WebTestClient as context path is a servlet concept. You can configure a baseUrl using WebTestClient but the app will have to be able to handle requests made to that URL.

I can't really offer any more advice than this as I don't know what you're trying to test (how it is implemented, for example), exactly how you're trying to test it, or why configuring the base path didn't meet your expectations.

Thank you for your response!

I understand that WebTestClient does not have a concept of context paths like servlets do. However, I want to ensure that when the curl requests are generated, they include the context path (e.g., /my-app).

The way you've mentioned it over here, this is exactly what I want to achieve with webclient.
image

I'm testing a api : http://localhost:4444/my-app/accounts/{accountId}/users

Setup

@BeforeEach
 void setUp(@Autowired final ApplicationContext context,
     final RestDocumentationContextProvider restDocumentation) { 

   this.webTestClient =
       WebTestClient.bindToApplicationContext(context).configureClient().baseUrl("http://localhost:4444/my-app")
        .filter(documentationConfiguration(restDocumentation).operationPreprocessors()
        .withResponseDefaults(prettyPrint()).withRequestDefaults(prettyPrint()))
        .build();
}

// Sample Test Case 

@Test
 void testGetUsersInAccountSuccess() {
   final String accountId = "123";

   // Mock Response
   final GetUsersInAccountResponseDto mockUser = createMockGetUsersInAccountResponse();

   // Mock service response
   when(userService.getUsersInAccount(accountId)).thenReturn(Mono.just(mockResponse));

   // Perform the test request
   webTestClient.get()
       .uri(
           "/accounts/{accountId}/users",accountId)
            .exchange().expectStatus().isOk().expectBody(GetUsersInAccountResponseDto.class)
         .value(response -> {
         	// assertions
       })
       .consumeWith(document("get-users-in-account-success",
           pathParameters(.....),
         responseFields(.....);
 }

When I run the test case with .baseUrl("http://localhost:4444/my-app") I get java.lang.AssertionError: Status expected:<200 OK> but was:<404 NOT_FOUND>

If I run the test case with .baseUrl("http://localhost:4444"). My test case is passed.

It seems that adding /my-app in the base URL is causing the issue. Is there any way I can include /my-app while still ensuring that the test passes?

You need to ensure that the path to which you're making a request is handling by one of the application's routes. For example, /my-app/accounts/{accountId}/users needs to be handled. If you don't want to change the server side, you could write a custom OperationPreprocessor that modifies the URI to change its path before it's documented.

Okay, Could you please give me more details on how to implement custom OperationPreprocessor
I checked but was not able to figure it out : https://stackoverflow.com/questions/33281509/spring-rest-docs-how-to-replace-parameters

Take a look at UriModifyingOperationPreprocessor for some inspiration. You should be able to change the path with some logic like this:

String rawPath = request.getUri().getRawPath();
uriBuilder.replacePath("/my-app" + ((rawPath != null) ? rawPath : ""));

I've opened #945 to track adding some support to REST Docs for this sort of URI pre-processing. I'll close this one as I don't think there's anything more to be done here.

Thank you !