Repository: springdoc/springdoc-openapi
Pull request #296 (2019-12-24 13:42:51)

Property `springdoc.api-docs.groups.enabled` removed
As not needed any more for enabling multiple OpenAPI definitions support.

Adding beans of type `GroupedOpenApi` should be enough for `springdoc` library to enable multiple OpenAPI definitions support.

Also I've found that currently endpoint `/swagger-config` for ` springdoc-openapi-webflux-ui` returns incorrect `urls` for multiple OpenAPI definitions. Should I fix this in this PR or create separate one?


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a8edfe68f..ec825d420 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
+## [1.2.21] - 
+
+### Removed
+- Property `springdoc.api-docs.groups.enabled` removed, as not needed any more for enabling multiple OpenAPI definitions support
+
 ## [1.2.20] - 2019-12-23
 
 ### Changed 
@@ -13,7 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ## [1.2.19] - 2019-12-22
 
-### Addded
+### Added
 - Support for Multiple OpenAPI definitions in one Spring Boot #213
 - Support for spring-context-indexer #262
 - Added support using properties from application.yml for description field in swagger-annotations #231
@@ -32,7 +37,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ## [1.2.18] - 2019-12-14
 
-### Addded
+### Added
 - Globally exclude params for webflux #228
 - Added ability to ignore param with @hidden annotation at class level #255
 - Support of spring.mvc.servlet.path #238
@@ -48,7 +53,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 ### Fixed
 - Fixes error with JDK 11 + Kotlin #248
 ## [1.2.17] - 2019-12-05
-### Addded
+### Added
 - Handle multiple endpoints on @GetParam #219
 
 ### Changed
diff --git a/springdoc-openapi-common/src/main/java/org/springdoc/core/Constants.java b/springdoc-openapi-common/src/main/java/org/springdoc/core/Constants.java
index c51aea04c..56423c403 100644
--- a/springdoc-openapi-common/src/main/java/org/springdoc/core/Constants.java
+++ b/springdoc-openapi-common/src/main/java/org/springdoc/core/Constants.java
@@ -11,8 +11,6 @@ public final class Constants {
     public static final String SWAGGER_CONFIG_URL = API_DOCS_URL + DEFAULT_PATH_SEPARATOR + SWAGGGER_CONFIG_FILE;
     public static final String DEFAULT_API_DOCS_URL_YAML = API_DOCS_URL + ".yaml";
     public static final String SPRINGDOC_ENABLED = "springdoc.api-docs.enabled";
-    public static final String SPRINGDOC_GROUPS_ENABLED = "springdoc.api-docs.groups.enabled";
-    public static final String SPRINGDOC_GROUPS_ENABLED_VALUE = "${" + SPRINGDOC_GROUPS_ENABLED + ":false}";
     public static final String SPRINGDOC_SWAGGER_UI_ENABLED = "springdoc.swagger-ui.enabled";
     public static final String SPRINGDOC_SHOW_ACTUATOR = "springdoc.show-actuator";
     public static final String SPRINGDOC_SHOW_ACTUATOR_VALUE = "${" + SPRINGDOC_SHOW_ACTUATOR + ":false}";
diff --git a/springdoc-openapi-common/src/main/java/org/springdoc/core/MultipleOpenApiSupportConfiguration.java b/springdoc-openapi-common/src/main/java/org/springdoc/core/MultipleOpenApiSupportConfiguration.java
deleted file mode 100644
index baa7b9eda..000000000
--- a/springdoc-openapi-common/src/main/java/org/springdoc/core/MultipleOpenApiSupportConfiguration.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.springdoc.core;
-
-import io.swagger.v3.oas.models.OpenAPI;
-import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-import static org.springdoc.core.Constants.SPRINGDOC_GROUPS_ENABLED;
-
-@Configuration
-@ConditionalOnProperty(name = SPRINGDOC_GROUPS_ENABLED)
-public class MultipleOpenApiSupportConfiguration {
-    @Bean
-    public BeanFactoryPostProcessor beanFactoryPostProcessor() {
-        return beanFactory -> {
-            for (String beanName : beanFactory.getBeanNamesForType(OpenAPI.class)) {
-                beanFactory.getBeanDefinition(beanName).setScope("prototype");
-            }
-            for (String beanName : beanFactory.getBeanNamesForType(OpenAPIBuilder.class)) {
-                beanFactory.getBeanDefinition(beanName).setScope("prototype");
-            }
-        };
-    }
-}
\ No newline at end of file
diff --git a/springdoc-openapi-ui/src/main/java/org/springdoc/ui/SwaggerWelcome.java b/springdoc-openapi-ui/src/main/java/org/springdoc/ui/SwaggerWelcome.java
index 631278171..4fd631aa5 100644
--- a/springdoc-openapi-ui/src/main/java/org/springdoc/ui/SwaggerWelcome.java
+++ b/springdoc-openapi-ui/src/main/java/org/springdoc/ui/SwaggerWelcome.java
@@ -15,7 +15,13 @@ import org.springframework.web.util.UriComponentsBuilder;
 import javax.servlet.http.HttpServletRequest;
 import java.util.Map;
 
-import static org.springdoc.core.Constants.*;
+import static org.springdoc.core.Constants.API_DOCS_URL;
+import static org.springdoc.core.Constants.MVC_SERVLET_PATH;
+import static org.springdoc.core.Constants.SPRINGDOC_SWAGGER_UI_ENABLED;
+import static org.springdoc.core.Constants.SWAGGER_CONFIG_URL;
+import static org.springdoc.core.Constants.SWAGGER_UI_PATH;
+import static org.springdoc.core.Constants.SWAGGER_UI_URL;
+import static org.springdoc.core.Constants.SWAGGGER_CONFIG_FILE;
 import static org.springframework.util.AntPathMatcher.DEFAULT_PATH_SEPARATOR;
 import static org.springframework.web.servlet.view.UrlBasedViewResolver.REDIRECT_URL_PREFIX;
 
@@ -35,9 +41,6 @@ class SwaggerWelcome {
     @Autowired
     private SwaggerUiConfigProperties swaggerUiConfig;
 
-    @Value(SPRINGDOC_GROUPS_ENABLED_VALUE)
-    private boolean groupsEnabled;
-
     @Operation(hidden = true)
     @GetMapping(SWAGGER_UI_PATH)
     public String redirectToUi(HttpServletRequest request) {
@@ -78,10 +81,12 @@ class SwaggerWelcome {
             String url = buildUrl(request, apiDocsUrl);
             String swaggerConfigUrl = url + DEFAULT_PATH_SEPARATOR + SWAGGGER_CONFIG_FILE;
             swaggerUiConfig.setConfigUrl(swaggerConfigUrl);
-            if (groupsEnabled)
-                SwaggerUiConfigProperties.addUrl(url);
-            else
+
+            if (SwaggerUiConfigProperties.getSwaggerUrls().isEmpty())
                 swaggerUiConfig.setUrl(url);
+            else
+                SwaggerUiConfigProperties.addUrl(url);
+
         }
     }
 }
\ No newline at end of file
diff --git a/springdoc-openapi-webflux-ui/src/main/java/org/springdoc/ui/SwaggerWelcome.java b/springdoc-openapi-webflux-ui/src/main/java/org/springdoc/ui/SwaggerWelcome.java
index 74c636e90..9bdcd7d08 100644
--- a/springdoc-openapi-webflux-ui/src/main/java/org/springdoc/ui/SwaggerWelcome.java
+++ b/springdoc-openapi-webflux-ui/src/main/java/org/springdoc/ui/SwaggerWelcome.java
@@ -35,8 +35,6 @@ public class SwaggerWelcome {
     private String uiPath;
     @Value(WEB_JARS_PREFIX_URL)
     private String webJarsPrefixUrl;
-    @Value(SPRINGDOC_GROUPS_ENABLED_VALUE)
-    private boolean groupsEnabled;
 
     @Bean
     @ConditionalOnProperty(name = SPRINGDOC_SWAGGER_UI_ENABLED, matchIfMissing = true)
@@ -60,10 +58,12 @@ public class SwaggerWelcome {
         if (StringUtils.isEmpty(swaggerUiConfig.getConfigUrl())) {
             String swaggerConfigUrl = apiDocsUrl + DEFAULT_PATH_SEPARATOR + SWAGGGER_CONFIG_FILE;
             swaggerUiConfig.setConfigUrl(swaggerConfigUrl);
-            if (groupsEnabled)
-                SwaggerUiConfigProperties.addUrl(apiDocsUrl);
-            else
+
+            if (SwaggerUiConfigProperties.getSwaggerUrls().isEmpty())
                 swaggerUiConfig.setUrl(apiDocsUrl);
+            else
+                SwaggerUiConfigProperties.addUrl(apiDocsUrl);
+
         }
     }
 
diff --git a/springdoc-openapi-webmvc-core/src/main/java/org/springdoc/core/MultipleOpenApiSupportConfiguration.java b/springdoc-openapi-webmvc-core/src/main/java/org/springdoc/core/MultipleOpenApiSupportConfiguration.java
new file mode 100644
index 000000000..dfdf4dd5e
--- /dev/null
+++ b/springdoc-openapi-webmvc-core/src/main/java/org/springdoc/core/MultipleOpenApiSupportConfiguration.java
@@ -0,0 +1,44 @@
+package org.springdoc.core;
+
+import io.swagger.v3.oas.models.OpenAPI;
+import org.springdoc.api.ActuatorProvider;
+import org.springdoc.api.MultipleOpenApiResource;
+import org.springframework.beans.factory.ObjectFactory;
+import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;
+
+import java.util.List;
+import java.util.Optional;
+
+
+@Configuration
+@ConditionalOnBean(GroupedOpenApi.class)
+public class MultipleOpenApiSupportConfiguration {
+
+    @Bean
+    public BeanFactoryPostProcessor beanFactoryPostProcessor() {
+        return beanFactory -> {
+            for (String beanName : beanFactory.getBeanNamesForType(OpenAPI.class)) {
+                beanFactory.getBeanDefinition(beanName).setScope("prototype");
+            }
+            for (String beanName : beanFactory.getBeanNamesForType(OpenAPIBuilder.class)) {
+                beanFactory.getBeanDefinition(beanName).setScope("prototype");
+            }
+        };
+    }
+
+    @Bean
+    public MultipleOpenApiResource multipleOpenApiResource(List<GroupedOpenApi> groupedOpenApis,
+                                                           ObjectFactory<OpenAPIBuilder> defaultOpenAPIBuilder, AbstractRequestBuilder requestBuilder,
+                                                           AbstractResponseBuilder responseBuilder, OperationBuilder operationParser,
+                                                           RequestMappingInfoHandlerMapping requestMappingHandlerMapping,
+                                                           Optional<ActuatorProvider> servletContextProvider) {
+        return new MultipleOpenApiResource(groupedOpenApis,
+                defaultOpenAPIBuilder, requestBuilder,
+                responseBuilder, operationParser,
+                requestMappingHandlerMapping, servletContextProvider);
+    }
+}
\ No newline at end of file
diff --git a/springdoc-openapi-webmvc-core/src/main/java/org/springdoc/core/SpringDocWebMvcConfiguration.java b/springdoc-openapi-webmvc-core/src/main/java/org/springdoc/core/SpringDocWebMvcConfiguration.java
index c9e27c87d..a8c0eb7c4 100644
--- a/springdoc-openapi-webmvc-core/src/main/java/org/springdoc/core/SpringDocWebMvcConfiguration.java
+++ b/springdoc-openapi-webmvc-core/src/main/java/org/springdoc/core/SpringDocWebMvcConfiguration.java
@@ -1,10 +1,8 @@
 package org.springdoc.core;
 
 import org.springdoc.api.ActuatorProvider;
-import org.springdoc.api.MultipleOpenApiResource;
 import org.springdoc.api.OpenApiCustomiser;
 import org.springdoc.api.OpenApiResource;
-import org.springframework.beans.factory.ObjectFactory;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
@@ -15,24 +13,10 @@ import java.util.List;
 import java.util.Optional;
 
 import static org.springdoc.core.Constants.SPRINGDOC_ENABLED;
-import static org.springdoc.core.Constants.SPRINGDOC_GROUPS_ENABLED;
 
 @Configuration
 public class SpringDocWebMvcConfiguration {
 
-
-    @Bean
-    @ConditionalOnProperty(name = SPRINGDOC_GROUPS_ENABLED)
-    public MultipleOpenApiResource multipleOpenApiResource(List<GroupedOpenApi> groupedOpenApis,
-                                                           ObjectFactory<OpenAPIBuilder> defaultOpenAPIBuilder, AbstractRequestBuilder requestBuilder,
-                                                           AbstractResponseBuilder responseBuilder, OperationBuilder operationParser,
-                                                           RequestMappingInfoHandlerMapping requestMappingHandlerMapping, Optional<ActuatorProvider> servletContextProvider) {
-        return new MultipleOpenApiResource(groupedOpenApis,
-                defaultOpenAPIBuilder, requestBuilder,
-                responseBuilder, operationParser,
-                requestMappingHandlerMapping, servletContextProvider);
-    }
-
     @Bean
     @ConditionalOnProperty(name = SPRINGDOC_ENABLED, matchIfMissing = true)
     public OpenApiResource openApiResource(OpenAPIBuilder openAPIBuilder, AbstractRequestBuilder requestBuilder,


Test patch:
diff --git a/springdoc-openapi-ui/src/test/java/test/org/springdoc/ui/app3/SpringDocApp3Test.java b/springdoc-openapi-ui/src/test/java/test/org/springdoc/ui/app3/SpringDocApp3Test.java
index 81db69dcb..3f3fb6700 100644
--- a/springdoc-openapi-ui/src/test/java/test/org/springdoc/ui/app3/SpringDocApp3Test.java
+++ b/springdoc-openapi-ui/src/test/java/test/org/springdoc/ui/app3/SpringDocApp3Test.java
@@ -7,6 +7,11 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
 import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
 import test.org.springdoc.ui.AbstractSpringDocTest;
 
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
 public class SpringDocApp3Test extends AbstractSpringDocTest {
 
     @Test
@@ -19,4 +24,13 @@ public class SpringDocApp3Test extends AbstractSpringDocTest {
                 .andExpect(MockMvcResultMatchers.status().isOk())
                 .andExpect(MockMvcResultMatchers.header().string(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_HTML_VALUE));
     }
+
+    @Test
+    public void swagger_config_for_no_groups() throws Exception {
+        mockMvc.perform(get("/v3/api-docs/swagger-config"))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("configUrl", equalTo("/v3/api-docs/swagger-config")))
+                .andExpect(jsonPath("url", equalTo("/v3/api-docs")))
+                .andExpect(jsonPath("urls").doesNotExist());
+    }
 }
diff --git a/springdoc-openapi-ui/src/test/java/test/org/springdoc/ui/app4/SpringDocApp4Test.java b/springdoc-openapi-ui/src/test/java/test/org/springdoc/ui/app4/SpringDocApp4Test.java
new file mode 100644
index 000000000..e00afb0b7
--- /dev/null
+++ b/springdoc-openapi-ui/src/test/java/test/org/springdoc/ui/app4/SpringDocApp4Test.java
@@ -0,0 +1,24 @@
+package test.org.springdoc.ui.app4;
+
+import org.junit.Test;
+import test.org.springdoc.ui.AbstractSpringDocTest;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+public class SpringDocApp4Test extends AbstractSpringDocTest {
+
+    @Test
+    public void swagger_config_for_multiple_groups() throws Exception {
+        mockMvc.perform(get("/v3/api-docs/swagger-config"))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("configUrl", equalTo("/v3/api-docs/swagger-config")))
+                .andExpect(jsonPath("url").doesNotExist())
+                .andExpect(jsonPath("urls[0].url", equalTo("/v3/api-docs/stores")))
+                .andExpect(jsonPath("urls[0].name", equalTo("stores")))
+                .andExpect(jsonPath("urls[1].url", equalTo("/v3/api-docs/pets")))
+                .andExpect(jsonPath("urls[1].name", equalTo("pets")));
+    }
+}
\ No newline at end of file
diff --git a/springdoc-openapi-ui/src/test/java/test/org/springdoc/ui/app4/SpringDocTestApp.java b/springdoc-openapi-ui/src/test/java/test/org/springdoc/ui/app4/SpringDocTestApp.java
new file mode 100644
index 000000000..f3ab8a1e3
--- /dev/null
+++ b/springdoc-openapi-ui/src/test/java/test/org/springdoc/ui/app4/SpringDocTestApp.java
@@ -0,0 +1,33 @@
+package test.org.springdoc.ui.app4;
+
+import org.springdoc.core.GroupedOpenApi;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+
+@SpringBootApplication
+public class SpringDocTestApp {
+
+    public static void main(String[] args) {
+        SpringApplication.run(SpringDocTestApp.class, args);
+    }
+
+    @Bean
+    public GroupedOpenApi storeOpenApi() {
+        String paths[] = {"/store/**"};
+        return GroupedOpenApi.builder()
+                .setGroup("stores")
+                .pathsToMatch(paths)
+                .build();
+    }
+
+    @Bean
+    public GroupedOpenApi groupOpenApi() {
+        String paths[] = {"/pet/**"};
+        return GroupedOpenApi.builder()
+                .setGroup("pets")
+                .pathsToMatch(paths)
+                .build();
+    }
+
+}
\ No newline at end of file
diff --git a/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app68/SpringDocApp68Test.java b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app68/SpringDocApp68Test.java
index 70990a803..8900e3d77 100644
--- a/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app68/SpringDocApp68Test.java
+++ b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app68/SpringDocApp68Test.java
@@ -9,27 +9,21 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.test.context.ActiveProfiles;
-import org.springframework.test.context.TestPropertySource;
 import org.springframework.test.context.junit4.SpringRunner;
 import org.springframework.test.web.servlet.MockMvc;
-import org.springframework.test.web.servlet.MvcResult;
 import test.org.springdoc.api.AbstractSpringDocTest;
 
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
 import static org.hamcrest.Matchers.is;
-import static org.skyscreamer.jsonassert.JSONAssert.assertEquals;
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+import static test.org.springdoc.utils.FileUtils.getContent;
 
 @RunWith(SpringRunner.class)
 @ActiveProfiles("test")
 @SpringBootTest
 @AutoConfigureMockMvc
-@TestPropertySource(properties = "springdoc.api-docs.groups.enabled=true")
 public class SpringDocApp68Test {
 
     protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractSpringDocTest.class);
@@ -41,45 +35,33 @@ public class SpringDocApp68Test {
 
     @Test
     public void testApp1() throws Exception {
-        MvcResult mockMvcResult = mockMvc.perform(get(Constants.DEFAULT_API_DOCS_URL + "/stores")).andExpect(status().isOk())
-                .andExpect(jsonPath("$.openapi", is("3.0.1"))).andReturn();
-        String result = mockMvcResult.getResponse().getContentAsString();
-        Path path = Paths.get(getClass().getClassLoader().getResource("results/app681.json").toURI());
-        byte[] fileBytes = Files.readAllBytes(path);
-        String expected = new String(fileBytes);
-        assertEquals(expected, result, true);
+        mockMvc.perform(get(Constants.DEFAULT_API_DOCS_URL + "/stores"))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.openapi", is("3.0.1")))
+                .andExpect(content().json(getContent("results/app681.json"), true));
     }
 
     @Test
     public void testApp2() throws Exception {
-        MvcResult mockMvcResult = mockMvc.perform(get(Constants.DEFAULT_API_DOCS_URL + "/users")).andExpect(status().isOk())
-                .andExpect(jsonPath("$.openapi", is("3.0.1"))).andReturn();
-        String result = mockMvcResult.getResponse().getContentAsString();
-        Path path = Paths.get(getClass().getClassLoader().getResource("results/app682.json").toURI());
-        byte[] fileBytes = Files.readAllBytes(path);
-        String expected = new String(fileBytes);
-        assertEquals(expected, result, true);
+        mockMvc.perform(get(Constants.DEFAULT_API_DOCS_URL + "/users"))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.openapi", is("3.0.1")))
+                .andExpect(content().json(getContent("results/app682.json"), true));
     }
 
     @Test
     public void testApp3() throws Exception {
-        MvcResult mockMvcResult = mockMvc.perform(get(Constants.DEFAULT_API_DOCS_URL + "/pets")).andExpect(status().isOk())
-                .andExpect(jsonPath("$.openapi", is("3.0.1"))).andReturn();
-        String result = mockMvcResult.getResponse().getContentAsString();
-        Path path = Paths.get(getClass().getClassLoader().getResource("results/app683.json").toURI());
-        byte[] fileBytes = Files.readAllBytes(path);
-        String expected = new String(fileBytes);
-        assertEquals(expected, result, true);
+        mockMvc.perform(get(Constants.DEFAULT_API_DOCS_URL + "/pets"))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.openapi", is("3.0.1")))
+                .andExpect(content().json(getContent("results/app683.json"), true));
     }
 
     @Test
     public void testApp4() throws Exception {
-        MvcResult mockMvcResult = mockMvc.perform(get(Constants.DEFAULT_API_DOCS_URL + "/groups")).andExpect(status().isOk())
-                .andExpect(jsonPath("$.openapi", is("3.0.1"))).andReturn();
-        String result = mockMvcResult.getResponse().getContentAsString();
-        Path path = Paths.get(getClass().getClassLoader().getResource("results/app684.json").toURI());
-        byte[] fileBytes = Files.readAllBytes(path);
-        String expected = new String(fileBytes);
-        assertEquals(expected, result, true);
+        mockMvc.perform(get(Constants.DEFAULT_API_DOCS_URL + "/groups"))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.openapi", is("3.0.1")))
+                .andExpect(content().json(getContent("results/app684.json"), true));
     }
 }
diff --git a/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/utils/FileUtils.java b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/utils/FileUtils.java
new file mode 100644
index 000000000..91cdcfa75
--- /dev/null
+++ b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/utils/FileUtils.java
@@ -0,0 +1,19 @@
+package test.org.springdoc.utils;
+
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class FileUtils {
+
+    public static String getContent(String fileName) {
+        try {
+            Path path = Paths.get(FileUtils.class.getClassLoader().getResource(fileName).toURI());
+            byte[] fileBytes = Files.readAllBytes(path);
+            return new String(fileBytes, StandardCharsets.UTF_8);
+        } catch (Exception e) {
+            throw new RuntimeException("Failed to read file: " + fileName, e);
+        }
+    }
+}
\ No newline at end of file