Подтвердить что ты не робот

Тест RESTful Services с RestTemplate

В моем приложении у меня много REST-сервисов. Я написал тесты для всех служб:

org.springframework.web.client.RestTemplate

Активация REST-Service, например. выглядит следующим образом:

final String loginResponse = restTemplate.exchange("http://localhost:8080/api/v1/xy", HttpMethod.POST, httpEntity, String.class)
        .getBody();

и после этого проверяю тело ответа - все работает нормально. Недостатком является то, что приложение обязательно должно быть запущено, чтобы вызвать REST-Services.

Теперь мой вопрос заключается в том, как я могу это сделать в своих методах [email protected]? Это приложение загрузки Spring (со встроенным tomcat).

Спасибо за помощь!

4b9b3361

Ответ 1

В этой документации есть хорошая глава, я предлагаю вам прочитать ее, чтобы полностью понять, что вы можете сделать.

Мне нравится использовать @IntegrationTest с настраиваемой конфигурацией, так как он запускает весь сервер и позволяет протестировать полную систему. Если вы хотите заменить некоторые части системы на mocks, вы можете сделать это, исключив определенные конфигурации или beans и заменив их на свой собственный.

Вот небольшой пример. Я оставил интерфейс MessageService, потому что он явно отличается от IndexController тем, что он делает, и его реализация по умолчанию - DefaultMessageService - потому что это не актуально.

Что он делает, так это то, что он закручивает все приложение за вычетом DefaultMessageService, но с его собственным MessageService. Затем он использует RestTemplate для выдачи реальных HTTP-запросов к запущенному приложению в тестовом случае.

Классы приложений:

IntegrationTestDemo.java:

@SpringBootApplication
public class IntegrationTestDemo {

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

}

IndexController.java:

@RestController
public class IndexController {

    @Autowired
    MessageService messageService;

    @RequestMapping("/")
    String getMessage() {
        return messageService.getMessage();
    }
}

Тестовые классы:

IntegrationTestDemoTest.java:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = TestConfig.class)
@WebIntegrationTest // This will start the server on a random port
public class IntegrationTestDemoTest {

    // This will hold the port number the server was started on
    @Value("${local.server.port}")
    int port;

    final RestTemplate template = new RestTemplate();

    @Test
    public void testGetMessage() {
        String message = template.getForObject("http://localhost:" + port + "/", String.class);

        Assert.assertEquals("This is a test message", message);
    }
}

TestConfig.java:

@SpringBootApplication
@ComponentScan(
    excludeFilters = {
        // Exclude the default message service
        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = DefaultMessageService.class),
        // Exclude the default boot application or it's
        // @ComponentScan will pull in the default message service
        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = IntegrationTestDemo.class)
    }
)
public class TestConfig {

    @Bean
    // Define our own test message service
    MessageService mockMessageService() {
        return new MessageService() {
            @Override
            public String getMessage() {
                return "This is a test message";
            }
        };
    }
}

Ответ 2

Если вы не искали тест конца (интегрирования), MockRestServiceServer может вам помочь. Мне было очень полезно отменить мои тестовые примеры от реальной службы.

Spring doc сказал:

Используется для тестов, которые включают прямое или косвенное использование RestTemplate. Предоставляет способ настроить ожидаемые запросы, которые будут выполняться через RestTemplate, а также макетные ответы для отправки назад, таким образом удаление необходимости для реального сервера.

Вот официальный официальный документ


Еще один совет: requestTo нельзя автоматически импортировать

server.expect(manyTimes(), requestTo("/hotels/42")) ....

Это статический метод org.springframework.test.web.client.match.MockRestRequestMatchers

Ответ 3

Поскольку вы используете Spring MVC для REST, я бы рекомендовал использовать средства тестирования, предоставленные путем создания экземпляров MockMVC() - таких как:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {
 ... // any required Spring config
)
@WebAppConfiguration
public class RestControllerTest {

    @Autowired
    private WebApplicationContext context;

    private MockMvc mockMvc;

    @Before
    public void setup() {
        mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
    }


    @Test
    public void getUserList() throws Exception {
        mockMvc.perform(get("/user"))
            .andExpect(status().isOk())
            .andExpect(content().contentType("application/json;charset=UTF-8")) 
            .andExpect(content().encoding("UTF-8"))
            .andExpect(jsonPath("$", hasSize(8)))
            .andExpect(jsonPath("$[0].id").exists())
            .andExpect(jsonPath("$[0].alias").exists())
            .andExpect(jsonPath("$[0].name").exists())
        );
    }
}

Этот unit test будет тестировать интерфейс REST без развертывания. В частности, возвращаются ли ровно 8 пользователей, а первый имеет поля "id", "alias" и "name".

В утверждениях jsonPath требуются две зависимости:

'com.jayway.jsonpath:json-path:0.8.1'
'com.jayway.jsonpath:json-path-assert:0.8.1'

И, возможно, также:

'org.springframework:spring-test:4.1.7.RELEASE'