Mock external server during integration testing with Spring -


i have spring web server on request makes external call third-party web api (e.g. retreive facebook oauth token). after getting data call computes response:

@restcontroller public class hellocontroller {     @requestmapping("/hello_to_facebook")     public string hello_to_facebook() {         // ask facebook         httpget httpget = new httpget(builduri("https", "graph.facebook.com", "/oauth/access_token"));         string response = httpclient.execute(httpget).getentity().tostring();         // .. response         return response;     } } 

i'm writing integration test checks hitting url on server leads expected result. want mock external server locally don't need internet access test this. best way this?

i'm novice in spring, have far.

@runwith(springjunit4classrunner.class) @springapplicationconfiguration(classes = application.class) @webappconfiguration @integrationtest({}) public class testhellocontrollerit {             @test     public void gethellotofacebook() throws exception {         string url = new url("http://localhost:8080/hello_to_facebook").tostring();         //somehow setup facebook server mock ...         //facebookservermock facebookmock = ...          resttemplate template = new testresttemplate();         responseentity<string> response = template.getforentity(url, string.class);         assertthat(response.getbody(), equalto("..."));          //assert facebook mock got called         //facebookmock.verify();     } } 

the actual real set more complicated - i'm making facebook oauth login , logic not in controller in various spring security objects. suspect testing code supposed same since i'm hitting urls , expect response, isn't it?

after playing bit various scenarios, here 1 way how can 1 achieve asked minimal interventions main code

  1. refactor controller use parameter thirdparty server address:

    @restcontroller public class hellocontroller {     @value("${api_host}")     private string apihost;      @requestmapping("/hello_to_facebook")     public string hello_to_facebook() {         // ask facebook         httpget httpget = new httpget(builduri("http", this.apihost, "/oauth/access_token"));         string response = httpclient.execute(httpget).getentity().tostring();         // .. response         return response + "_processed";     } } 

'api_host' equals 'graph.facebook.com' in application.properties in src/main/resources

  1. create new controller in src/test/java folder mocks thirdparty server.

  2. override 'api_host' testing 'localhost'.

here code steps 2 , 3 in 1 file 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 facebook mock got called:         // example add flag mock, mock bean, check flag     } } 

is there nicer way this? feedback appreciated!

p.s. here complications encountered putting answer more realistic app:

  1. eclipse mixes test , main configuration classpath might screw main configuration test classes , parameters: https://issuetracker.springsource.com/browse/sts-3882 use gradle bootrun avoid it

  2. you have open access mocked links in security config if have spring security set up. append security config instead of messing 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);     } } 
  3. it not straightforward hit https links in integration tests. end using testresttemplate custom request factory , configured sslconnectionsocketfactory.


Popular posts from this blog