Java >> Java tutorial >  >> Tag >> Spring

Mock ekstern server under integrationstest med Spring

Efter at have leget lidt med forskellige scenarier, her er den ene måde, hvordan man kan opnå det, der blev bedt om med minimale indgreb i hovedkoden

  1. Refaktorer din controller til at bruge en parameter til tredjeparts serveradresse:

    @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' er lig med 'graph.facebook.com' i application.properties i src/main/resources

  1. Opret en ny controller i mappen src/test/java, der håner tredjepartsserveren.

  2. Tilsidesæt 'api_host' for at teste til 'localhost'.

Her er koden til trin 2 og 3 i én fil for kortheds skyld:

@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
    }
}

Er der en bedre måde at gøre dette på? Al feedback er værdsat!

P.S. Her er nogle komplikationer, jeg stødte på ved at sætte dette svar ind i en mere realistisk app:

  1. Eclipse blander test- og hovedkonfiguration i klassesti, så du kan skrue op for din hovedkonfiguration med testklasser og parametre:https://issuetracker.springsource.com/browse/STS-3882 Brug gradle bootRun for at undgå det

  2. Du skal åbne adgang til dine hånede links i sikkerhedskonfigurationen, hvis du har opsat forårssikkerhed. For at tilføje til en sikkerhedskonfiguration i stedet for at rode med en hovedkonfigurationskonfiguration:

    @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);
        }
    }
    
  3. Det er ikke ligetil at ramme https-links i integrationstest. Jeg ender med at bruge TestRestTemplate med custom request factory og konfigureret SSLConnectionSocketFactory.


Java tag