如何在Spring Boot Application的测试目录中创建Rest Controller

问题描述 投票:0回答:1

我目前正在为SpringBoot Application编写集成测试。它的功能是从外部接收/发送请求并将其转发/接收到另一个应用程序(APP_2)。因此,有两个系统需要在System和APP_2之外进行模拟。

ProjectStructure

HomeController的

@Controller
public class HomeController {
    @Autowired
    ForwardController forwardController;

    @RequestMapping("/")
    public @ResponseBody
    String greeting() {
    return forwardController.processGET().toString();
    }
}

ForwardController

@Service
public class ForwardController {
    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private Environment environment;

    private ResponseEntity sendRequest(String url, HttpMethod method, HttpEntity requestEntity, Class responseType, Object... uriVariables) {
    return restTemplate.exchange( url,  method, requestEntity,  responseType,uriVariables);
    }

    public ResponseEntity processGET()
    {
        HttpHeaders headers = new HttpHeaders();
        headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);

        HttpEntity<?> entity = new HttpEntity<>(headers);
        String app_2_url = environment.getProperty(Constants.APP_2_URL);
        ResponseEntity<String> response = sendRequest(app_2_url,HttpMethod.GET,entity,String.class);
        return response;
    }
}

APP_2_CONTROLLER

@Controller
public class App_2_Controller {

    @RequestMapping("/app2Stub")
    public @ResponseBody
    String greeting() {
        return "Hello End of world";
    }
}

测试类,它模拟系统的外部请求行为:

HTTP_request_Test

@RunWith(SpringRunner.class)
@ActiveProfiles("test")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,classes = Application.class)
public class HttpRequestTest {

    @LocalServerPort
    private int port;

    @Autowired
    private TestRestTemplate restTemplate;

    @Autowired
    private Environment environment;

    @Test
    public void greetingShouldReturnDefaultMessage() throws Exception {
      assertThat(this.restTemplate.getForObject("http://localhost:" + port + "/",
            String.class)).contains("Hello End of world");
    }
}

在这个测试类中,我通过拥有两个属性文件来覆盖属性。因此,当我们运行测试时,请求将被发送到App_2_Controller(我的项目中的模拟),而不是真正的应用程序。

题 :

  1. 有没有办法让APP_2_CONTROLLER在测试文件夹中?这是因为我不想在我的Actual应用程序中公开不需要的测试端点。
  2. 在上面的项目中,我用属性更改URL。有没有更好的方法将控制器放在同一个URL上。为简单起见,我们假设,app_2 url是app.com:9000/serve
spring-boot spring-mvc spring-test spring-restcontroller spring-boot-test
1个回答
1
投票

Spring已经附带了MockRestServiceServer,这使得它更容易,因此您不必创建自己的虚拟控制器(App_2_Controller)。所以在你的情况下,你可以删除那个控制器,并为ForwardController写一个这样的测试:

@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles("test")
public class ForwardControllerTest {
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private ForwardController forwardController; // Your service

    private MockRestServiceServer server;

    @Before
    public void setUp() {
        server = MockRestServiceServer.bindTo(restTemplate).build();
    }

    @Test
    public void processGet_returnsResponseFromAPI() {
        server.expect(once(), requestTo("http://app.com:9000/serve"))
            .andExpect(method(HttpMethod.GET))
            .andRespond(withSuccess("Hello End of world", MediaType.TEXT_PLAIN));
        assertThat(forwardController.processGET().getBody()).isEqualTo("Hello End of world"));
    }
}

另外,你可以为你的实际控制器创建一个单独的测试(ForwardController只是一个服务),模拟ForwardController并使用MockMvc

@RunWith(SpringRunner.class)
@WebMvcTest
public class HomeControllerTest {
    @Autowired
    private HomeController homeController;
    @Autowired
    private MockMvc mockMvc;
    @MockBean
    private ForwardController forwardController;

    @Test
    public void greeting_usesForwardController() {
        when(forwardController.expectGET()).thenReturn("Hello End of world");
        mockMvc.perform(get("/"))
            .andExpect(status().isOk())
            .andExpect(content().string(containsString("Hello End of world")));
    }
}

在这种情况下,您最终将进行两项测试:

  1. 一个测试验证RestTemplate用于从外部REST API捕获正确的响应。
  2. 另一个测试验证HomeController只是转发任何ForwardController响应。
© www.soinside.com 2019 - 2024. All rights reserved.