Testing CORs in SpringBootTest

test cors
test cors with postman
firefox test cors
testing cors on localhost
cors error test
spring security cors
spring 5 cors
spring boot cors

Im trying to write a test to verify our CORS settings. I configure CORS like this.

@Override
    public void configure(HttpSecurity httpSecurity) throws Exception {
//        super.configure(httpSecurity);
        httpSecurity.csrf().disable();
        httpSecurity.authorizeRequests().antMatchers("/**").permitAll();
        httpSecurity.cors();
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        List<String> allowedMethods = CORS_ALLOWED_METHODS;
        configuration.setAllowedMethods(allowedMethods);
        configuration.setAllowedOrigins(CORS_ALLOWED_ORIGINS);
        configuration.setAllowedHeaders(CORS_ALLOWED_HEADERS);
        configuration.setAllowCredentials(true);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

I have verified with the debugger that CORS_ALLOWED_METHODS has values when my test runs.

Here is my test. It fails when I assert on the headers.

@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles("dev")
public class ControllerTests {

    @Autowired
    private WebApplicationContext wac;

    public MockMvc mockMvc;

    @Before
    public void setup() {
        DefaultMockMvcBuilder builder = MockMvcBuilders
                .webAppContextSetup(this.wac)
                .apply(SecurityMockMvcConfigurers.springSecurity())
                .dispatchOptions(true);
        this.mockMvc = builder.build();
    }

    @Test
    public void testCors() throws Exception {
        this.mockMvc
                .perform(get("/test-cors"))
                .andDo(print())
                .andExpect(status().isOk())
                .andExpect(header().string("Access-Control-Allow-Methods", "OPTIONS,GET,HEAD,POST,PUT,DELETE,TRACE,CONNECT"))
                .andExpect(content().string("whatever"));
    }

    @SpringBootApplication(scanBasePackages = {"the.packages"})
    @Controller
    static class TestApplication {

        public static void main(String[] args) throws Exception {
            SpringApplication.run(TestApplication.class, args);
        }

        @RequestMapping(value = {"test-cors"},  method = RequestMethod.GET)
        @ResponseStatus(HttpStatus.OK)
        public @ResponseBody String testCors() {
            return "whatever";
        }
    }
}

As a note, when I actually run a SpringBoot app with this configuration we do get CORS headers.

Any help appreciated.

The CORS request needs to include an Origin header for the server to process it. The mock GET request is not having this header. The API does allow us to include headers in the mock requests.

public MockHttpServletRequestBuilder header(String name, Object... values)

Add a header to the request. Values are always added. Parameters: name - the header name values - one or more header values

Here is the code that works

.perform(options("/test-cors")
    .header("Access-Control-Request-Method", "GET")
    .header("Origin", "http://www.someurl.com"))

Both headers are required, and the configuration requires that allowed origins and methods align with the values passed in the test.

How test CORS in Spring Boot? When I try in MockMvcBuilders, it , To check CORS a preflight call to the URL has to be made. That is not a POST but an OPTIONS request against the very same URL with the CORS headers. With that call you will receive the CORS response if the real call (against DELETE) is allowed or not. Spring Boot provides an easy way to write a Unit Test for Rest Controller file. With the help of SpringJUnit4ClassRunner and MockMvc, we can create a web application context to write Unit Test for Rest Controller file. Unit Tests should be written under the src/test/java directory and classpath resources for writing a test should be placed

Instead of initializing the CorsConfigurationSource Bean Simply initialize CorsFilter straight up. Just change that method like this and try,

@Bean
public CorsFilter corsFilter() {
        CorsConfiguration configuration = new CorsConfiguration();
        List<String> allowedMethods = CORS_ALLOWED_METHODS;
        configuration.setAllowedMethods(allowedMethods);
        configuration.setAllowedOrigins(CORS_ALLOWED_ORIGINS);
        configuration.setAllowedHeaders(CORS_ALLOWED_HEADERS);
        configuration.setAllowCredentials(true);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return new CorsFilter(source);
}

HTH!

test-cors.org, ) is a W3C specification implemented by most browsers that allows you to specify in a flexible way what kind of cross domain requests are authorized, instead of using some less secured and less powerful hacks like IFrame or JSONP. @RunWith(SpringRunner.class) is used to provide a bridge between Spring Boot test features and JUnit. Whenever we are using any Spring Boot testing features in our JUnit tests, this annotation will be required. @DataJpaTest provides some standard setup needed for testing the persistence layer: configuring H2, an in-memory database

Another way to write a test for CORS settings is by performing a mock request on predefined url and then assert its MockHttpServletResponse. Here is the code that works for me:

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
@ActiveProfiles("corsFilterBean")
public class CORSFilterTests {

@Autowired
private MockMvc mvc;

@Test
public void test_corsFilterBean() throws Exception {

    MvcResult result = mvc
            .perform(get("/users/all"))
            .andExpect(status().isOk())
            .andExpect(header().string("Access-Control-Allow-Origin", "*"))
            .andExpect(header().string("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE"))
            .andExpect(header().string("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, X-Auth-Token, X-Csrf-Token, WWW-Authenticate, Authorization"))
            .andExpect(header().string("Access-Control-Expose-Headers", "custom-token1, custom-token2"))
            .andExpect(header().string("Access-Control-Allow-Credentials", "false"))
            .andExpect(header().string("Access-Control-Max-Age", "3600"))
            .andDo(print())
            .andReturn();

    MockHttpServletResponse mockResponse = result.getResponse();

    assertThat(mockResponse.getContentType()).contains("application/json;charset=UTF-8");

    Collection<String> responseHeaders = mockResponse.getHeaderNames();
    assertThat(responseHeaders).isNotNull();
    assertThat(1).isEqualTo(1);
    assertThat(responseHeaders.size()).isBetween(5, 15);
  }
}

This assumes that there's a CORS specification class which enables cross-origin requests. Here's a sample of my CORS Filter class:

public class CORSFilterss extends GenericFilterBean implements Filter {

private Logger logger = LoggerFactory.getLogger(this.getClass());

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {

    HttpServletResponse httpResponse = (HttpServletResponse) response;
    httpResponse.setHeader("Access-Control-Allow-Origin", "*");
    httpResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
    httpResponse.setHeader("Access-Control-Allow-Headers",
            "Origin, X-Requested-With, Content-Type, Accept, X-Auth-Token, X-Csrf-Token, WWW-Authenticate, Authorization");
    httpResponse.setHeader("Access-Control-Expose-Headers", "custom-token1, custom-token2");
    httpResponse.setHeader("Access-Control-Allow-Credentials", "false");
    httpResponse.setHeader("Access-Control-Max-Age", "3600");

    StringBuilder sb = new StringBuilder();
    sb.append("\nCORS HEADERS:\n");
    sb.append("---------------\n");
    httpResponse.getHeaderNames()
            .forEach(name -> {
                        sb.append(name).append(": ").append(httpResponse.getHeader(name)).append("\n");
                    }
            );
    logger.debug("********** CORS Configuration Completed **********");
    logger.debug(sb.toString());

    chain.doFilter(request, response);
  }
} 

Also, the spring boot main application class contains a FilterRegistrationBean which registers the CORS filter class. Here's a sample of my main applicaton class:

@SpringBootApplication
public class SpringTestingApplication implements CommandLineRunner {

public static void main(String[] args) {
    SpringApplication.run(SpringTestingApplication.class, args);
}
@Override
public void run(String... args) throws Exception {

}
@Bean
public FilterRegistrationBean corsFilterRegistration() {
    FilterRegistrationBean registrationBean =
            new FilterRegistrationBean(new CORSFilterss());
    registrationBean.setName("CORS FILTER");
    registrationBean.addUrlPatterns("/*");
    registrationBean.setOrder(1);

    return registrationBean;

  }
}

You can get more from this github demo app

Spring CORS - @CrossOrigin and CorsRegistry, BeforeClass;. import org.testng.annotations.Test;. import org.testng.Assert;. import com.ge.predix.web.cors.CORSFilter;. @Test. public class CORSFilterTest {. The spring-boot-starter-test dependency includes all required dependencies to create and execute tests. The HTTP APIs are defined in controller are given below. In given tests, we are testing two GET apis – one without path parameter and another with path parameter. @Autowired private MockMvc mvc

Here is what I've done. I've used Configuration @Configuration for enabling CORS using Springboot. Here is my class:

In your applicatoin.properties file, you can add your property and domains as below:

allowed.origins=.someurl.com,.otherurl.com,*.someotherurl.com

And your your Config Class:

@Configuration @EnableWebMvc public class AppConfig extends WebMvcConfigurerAdapter {

private static final Logger logger = LoggerFactory.getLogger(AppConfig.class);

@Value("#{'${allowed.origins}'.split(',')}")
private List<String> rawOrigins;

@Bean
public RestTemplate restTemplate() {
    return new RestTemplate();
}

@Bean
public WebMvcConfigurer corsConfigurer() {
    return new WebMvcConfigurerAdapter() {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            logger.info("Adding CORS to the APP");
            registry.addMapping("/**")
                        .allowedOrigins(getOrigin())
                    .allowedMethods(HttpMethod.GET.name(), HttpMethod.POST.name(), HttpMethod.OPTIONS.name())
                    .allowedHeaders(HttpHeaders.AUTHORIZATION, HttpHeaders.CONTENT_TYPE, "accessToken", "CorrelationId", "source")
                    .exposedHeaders(HttpHeaders.AUTHORIZATION, HttpHeaders.CONTENT_TYPE, "accessToken", "CorrelationId", "source")
                    .maxAge(4800);
        }
        /**
         * This is to add Swagger to work when CORS is enabled
         */
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {

               registry.addResourceHandler("swagger-ui.html")
                        .addResourceLocations("classpath:/META-INF/resources/");

                registry.addResourceHandler("/webjars/**")
                        .addResourceLocations("classpath:/META-INF/resources/webjars/");

        }
    };
}


public String[] getOrigin() {
    int size = rawOrigins.size();
    String[] originArray = new String[size];
    return rawOrigins.toArray(originArray);
}

}

Here is my test class for the Controllers:

@RunWith(SpringRunner.class)
@WebMvcTest(AuthController.class)
@AutoConfigureMockMvc(secure=false)
@SuppressWarnings("unchecked")
public class AuthControllerTest {

public static final String EXPIRES_IN = "expiresIn";
public static final String TOKEN_TYPE = "tokenType";
public static final String SCOPE = "scope";
public static final String ID_TOKEN = "idToken";
@Autowired
private MockMvc mockMvc;

@MockBean
private AuthService service;

@Mock
private WebMvcConfigurer corsConfigurer;

private static final ObjectMapper objectMapper = new ObjectMapper();

private static final String RESPONSE_JSON = "{\"response\":\"result\"}";

private static final String REDIRECT_URL = "url";

private static final String CODE = "code";

private static final String STATE = "state";

private static final String ACCESS_TOKEN = "accessToken";

private static final Map<String, String> requestHeaders = new HashMap<>();

@Before
public void setup() {
        requestHeaders.put("source", "source");
        requestHeaders.put("CorrelationId", "CorrelationId");
}

/**
* Controller Test to pass the CORS
*/
@Test
public void testGetLoginUrl() throws Exception {
    when(service.getLoginUrl(anyString(),anyMap())).thenReturn(objectMapper.readTree(RESPONSE_JSON));
    this.mockMvc.perform(get("/vendor/auth/loginurl?redirect_url="+ REDIRECT_URL)
            .header("CorrelationId", "1234")
            .header("Origin", "http://localhost:8080"))
            .andDo(print())
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.response", is("result")));

}
}

Please note that, in the Test Class, I'm mocking WebMvcConfigurer which will internally add the CORS Registry and will initialize it for your SpringTest.

However, you'll need to pass Origin in your header; without which you'll get 403 - Forbidden response from your Controller.

CORS support in Spring Framework, CORSFilter doesn't work with @SpringBootTest #17007. Closed. kbyyd24 opened this After that, I added a test class to test the cors config. test-cors.org. Use this page to test CORS requests. You can either send the CORS request to a remote server (to test if CORS is supported), or send the CORS request to a test server (to explore certain features of CORS).

spring-cors-filter/CORSFilterTest.java at master · predix/spring-cors , Im trying to write a test to verify our CORS settings. I configure CORS like this. @​Override public void configure(HttpSecurity httpSecurity) throws Exception  The TestEntityManager in the above test is provided by Spring Boot. It’s an alternative to the standard JPA EntityManager that provides methods commonly used when writing tests. Testing the Spring MVC slice To test the Spring MVC slice of your application you can use the @WebMvcTest annotation.

CORSFilter doesn't work with @SpringBootTest · Issue #17007 , Simple config for CORS with the built-in support in Spring MVC. fundamentals of Spring 5 and Spring Boot 2: >> CHECK OUT THE COURSE  The test assertion is the same as in the previous case, but here Spring Boot is only instantiating the web layer, not the whole context. In an application with multiple controllers you can even ask for just one to be instantiated, using, for example @WebMvcTest(HomeController.class) So far,

Testing CORs in SpringBootTest, Ask questionsCORSFilter doesn't work with @SpringBootTest. I created a demo about After that, I added a test class to test the cors config Setting Up the Test Class. To test our API, we will create a test class annotated with @SpringBootTest that uses the AuthorizationServerApplication class to read the application configuration. For testing a secured API with Spring MVC test support, we need to inject the WebAppplicationContext and Spring Security Filter Chain beans.

Comments
  • I think you should add the http Origin header to a value that you want to test while creating your mock GET request. I suspect Spring doesn't processes your request for CORS without an origin.
  • Yes I figured that out this morning. If you write it as an answer Ill accept.
  • Updated your answer with some example code. I also needed to specify Access-Control-Request-Method.