2017-10-11 51 views
1

下面的测试(我包括两个类来查看是否可以工作)都没有调用控制器的问题。我希望它拒绝CORS问题,因为我没有添加任何CORS配置。 (然后我想用CORS配置进行测试并通过)。如何在Spring Boot中测试CORS?当我尝试使用MockMvcBuilders时,尽管起源错误,它始终返回200

我该如何强制CORS失败?

第一次尝试:

import com.testing.Application; 
import com.testing.config.ControllerConfig; 
import com.testing.controller.MyController; 
import com.testing.dto.TestDateResponse; 
import com.testing.exception.GlobalExceptionHandler; 
import com.testing.service.TestService; 
import com.fasterxml.jackson.databind.ObjectMapper; 
import org.junit.Before; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.mockito.InjectMocks; 
import org.mockito.MockitoAnnotations; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.boot.test.context.SpringBootTest; 
import org.springframework.http.MediaType; 
import org.springframework.test.context.ContextConfiguration; 
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 
import org.springframework.test.context.web.WebAppConfiguration; 
import org.springframework.test.web.servlet.MockMvc; 
import org.springframework.test.web.servlet.ResultActions; 
import org.springframework.test.web.servlet.setup.MockMvcBuilders; 
import org.springframework.web.client.RestTemplate; 
import org.springframework.web.context.ConfigurableWebApplicationContext; 

import java.time.LocalDate; 

import static org.hamcrest.Matchers.equalTo; 
import static org.hamcrest.Matchers.notNullValue; 
import static org.junit.Assert.assertThat; 
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; 
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringBootTest(classes = Application.class) 
@WebAppConfiguration 
public class TestCORS 
{ 
    @Autowired 
    private ConfigurableWebApplicationContext context; 

    private MockMvc mockMvc; 
    private ObjectMapper objectMapper; 

    @InjectMocks 
    private MyController myController; 

    @Autowired 
    private RestTemplate restTemplate; 

    @Before 
    public void setup() 
    { 
     //Initialize our injected mocks 
     MockitoAnnotations.initMocks(this); 

     //Create a controller 
     myController = new MyController(new TestService(), restTemplate); 

     //Create an environment for it 
     mockMvc = MockMvcBuilders 
      .webAppContextSetup(context) 
      .dispatchOptions(true) 
      .build(); 

     //Create our marshaller 
     objectMapper = new ObjectMapper(); 
    } 

    /** 
    * Tests that we fail when trying to access cross origin 
    * @throws Exception if json unmarshaller cannot parse the response 
    */ 
    @Test 
    public void testValidRequest() throws Exception 
    { 
     String request = "{\"asOfDate\":\"20170210\"}"; 

     //Call to test a date 
     ResultActions actions = mockMvc.perform(
      post("/v1/testdate") 
       .contentType(MediaType.APPLICATION_JSON) 
       .content(request) 

       //CORS HEADERS 
       .header("Access-Control-Request-Method", "DELETE") 
       .header("Origin", "https://evil.com") 
     ); 

     actions.andExpect(status().isOk()) 
      .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)); 

     TestDateResponse response = objectMapper.readValue(actions.andReturn().getResponse().getContentAsString(), TestDateResponse.class); 
     assertThat(response, notNullValue()); 
     // verify date has returned back correctly 
     assertThat(response.getRetDate(), equalTo(LocalDate.of(2017, 02, 10))); 
    } 
} 

第二次尝试:

import com.testing.config.ControllerConfig; 
import com.testing.controller.MyController; 
import com.testing.dto.TestDateResponse; 
import com.testing.exception.GlobalExceptionHandler; 
import com.testing.service.TestService; 
import com.fasterxml.jackson.databind.ObjectMapper; 
import org.junit.Before; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.mockito.MockitoAnnotations; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.http.MediaType; 
import org.springframework.test.context.ContextConfiguration; 
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 
import org.springframework.test.web.servlet.MockMvc; 
import org.springframework.test.web.servlet.ResultActions; 
import org.springframework.test.web.servlet.setup.MockMvcBuilders; 
import org.springframework.web.client.RestTemplate; 

import java.time.LocalDate; 

import static org.hamcrest.Matchers.equalTo; 
import static org.hamcrest.Matchers.notNullValue; 
import static org.junit.Assert.assertThat; 
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; 
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(classes = {ControllerConfig.class}) 
public class TestCORS 
{ 
    private MockMvc mockMvc; 
    private ObjectMapper objectMapper; 
    private MyController myController; 

    @Autowired 
    private RestTemplate restTemplate; 

    @Before 
    public void setup() 
    { 
     //Initialize our injected mocks 
     MockitoAnnotations.initMocks(this); 

     //Create a controller 
     myController = new MyController(new TestService(), restTemplate); 

     //Create an environment for it 
     mockMvc = MockMvcBuilders.standaloneSetup(myController) 
      .setControllerAdvice(new GlobalExceptionHandler()) 
      .build(); 

     //Create our marshaller 
     objectMapper = new ObjectMapper(); 
    } 

    /** 
    * Tests that we fail when trying to access cross origin 
    * @throws Exception if json unmarshaller cannot parse the response 
    */ 
    @Test 
    public void testValidRequest() throws Exception 
    { 
     String request = "{\"asOfDate\":\"20170210\"}"; 

     //Call to test a date 
     ResultActions actions = mockMvc.perform(
      post("/v1/testdate") 
       .contentType(MediaType.APPLICATION_JSON) 
       .content(request) 

       //CORS HEADERS 
       .header("Access-Control-Request-Method", "GET") 
       .header("Origin", "http://www.someurl.com") 
     ); 
     actions.andExpect(status().isOk()) 
      .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)); 

     TestDateResponse response = objectMapper.readValue(actions.andReturn().getResponse().getContentAsString(), TestDateResponse.class); 
     assertThat(response, notNullValue()); 
     // verify date has returned back correctly 
     assertThat(response.getRetDate(), equalTo(LocalDate.of(2017, 02, 10))); 
    } 
} 

回答

0

CORS不喜欢的工作。

要检查CORS,必须对URL执行预检操作。 这不是一个POST,而是一个OPTIONS请求,针对与CORS头部完全相同的URL。

通过该调用,如果允许或不允许真正的调用(禁止DELETE),您将收到CORS响应。

类似的东西应该工作:

ResultActions actions = mockMvc.perform(
     options("/v1/testdate")  
      .contentType(MediaType.APPLICATION_JSON) 
      //CORS HEADERS 
      .header("Access-Control-Request-Method", "DELETE") 
      .header("Origin", "https://evil.com") 
    ); 

,然后简单地断言的预期响应头。

+0

我得到这个错误:'javax.servlet.ServletException:处理程序没有适配器[org.springframew[email protected]82c57b3]:DispatcherServlet配置需要包含一个HandlerAdapter来支持这个处理程序' –

+0

您是否在您的RequestController或您的RequestMapping上配置了交叉原点?例如与:@CrossOrigin(origins =“http://not-evil.com”) –

+0

不,我不知道。我需要吗?这会解决这个错误吗? 有没有办法让自定义的适配器bean摆脱这个错误? –

相关问题