更新时间:2022-03-17 23:15:48
在玩完各种场景之后,这是一种方法,它可以在对主代码进行最少干预的情况下实现所要求的内容
After playing a bit with various scenarios, here is the one way how can one achieve what was asked with minimal interventions to the main code
重构您的控制器以将参数用于第三方服务器地址:
Refactor your controller to use a parameter for thirdparty server address:
@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'等于src/main/resources中application.properties中的'graph.facebook.com'
'api_host' equals to 'graph.facebook.com' in application.properties in the src/main/resources
在src/test/java文件夹中创建一个模拟第三方服务器的新控制器.
Create a new controller in the src/test/java folder that mocks the thirdparty server.
覆盖"api_host"以测试到"localhost".
Override 'api_host' for testing to 'localhost'.
为简便起见,以下是一个文件中第2步和第3步的代码:
Here is the code for steps 2 and 3 in one file for brevity:
@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
}
}
有没有更好的方法可以做到这一点?感谢所有反馈!
Is there a nicer way to do this? All feedback is appreciated!
P.S.这是我将这个答案放到更现实的应用程序中遇到的一些复杂问题:
P.S. Here are some complications I encountered putting this answer into more realistic app:
Eclipse将测试和主要配置混合到类路径中,因此您可以通过测试类和参数来破坏主要配置: https://issuetracker.springsource.com/browse/STS-3882 使用gradle bootRun避免它
Eclipse mixes test and main configuration into classpath so you might screw up your main configuration by test classes and parameters: https://issuetracker.springsource.com/browse/STS-3882 Use gradle bootRun to avoid it
如果已设置spring安全性,则必须在安全性配置中打开对模拟链接的访问权限.要附加到安全性配置而不是与主配置混淆,请执行以下操作:
You have to open access to your mocked links in the security config if you have spring security set up. To append to a security config instead of messing with a main configuration config:
@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与自定义请求工厂一起使用,并配置了SSLConnectionSocketFactory.
It is not straightforward to hit https links in integration tests. I end up using TestRestTemplate with custom request factory and configured SSLConnectionSocketFactory.