Ответ 1
Немного поработав с различными сценариями, вот один из способов, как можно достичь того, что было задано с минимальными вмешательствами в основной код.
-
Рефакторинг вашего контроллера для использования параметра для адреса сервера третьей стороны:
@RestController public class HelloController { @Value("${api_host}") private String apiHost; @RequestMapping("/hello_to_facebook") public String hello_to_facebook() { // Ask facebook about something HttpGet httpget = new HttpGet(buildURI("http", this.apiHost, "/oauth/access_token")); String response = httpClient.execute(httpget).getEntity().toString(); // .. Do something with a response return response + "_PROCESSED"; } }
'api_host' равен 'graph.facebook.com' в application.properties в src/main/resources
-
Создайте новый контроллер в папке src/test/java, который высмеивает сервер третьей стороны.
-
Переопределить 'api_host' для тестирования на 'localhost'.
Ниже приведен код для шагов 2 и 3 в одном файле для краткости:
@RestController
class FacebookMockController {
@RequestMapping("/oauth/access_token")
public String oauthToken() {
return "TEST_TOKEN";
}
}
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
@IntegrationTest({"api_host=localhost",})
public class TestHelloControllerIT {
@Test
public void getHelloToFacebook() throws Exception {
String url = new URL("http://localhost:8080/hello_to_facebook").toString();
RestTemplate template = new TestRestTemplate();
ResponseEntity<String> response = template.getForEntity(url, String.class);
assertThat(response.getBody(), equalTo("TEST_TOKEN_PROCESSED"));
// Assert that facebook mock got called:
// for example add flag to mock, get the mock bean, check the flag
}
}
Есть ли лучший способ сделать это? Все отзывы приветствуются!
P.S. Вот некоторые сложности, с которыми я столкнулся, поставив этот ответ в более реалистичное приложение:
-
Eclipse смешивает тест и основную конфигурацию в classpath, поэтому вы можете испортить свою основную конфигурацию с помощью тестовых классов и параметров: https://issuetracker.springsource.com/browse/STS-3882 Используйте gradle bootRun, чтобы избежать этого
-
При настройке безопасности spring вы должны открыть доступ к вашим издеваемым ссылкам в конфиге безопасности. Чтобы добавить в конфигурацию безопасности вместо того, чтобы возиться с конфигурацией основной конфигурации:
@Configuration @Order(1) class TestWebSecurityConfig extends WebSecurityConfig { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/oauth/access_token").permitAll(); super.configure(http); } }
-
Непросто ударить https-ссылки в тестах интеграции. Я в конечном итоге использую TestRestTemplate с пользовательским запросом factory и настроил SSLConnectionSocketFactory.