Last active
May 26, 2023 09:23
-
-
Save silkentrance/b5adb52d943555671a44e88356c889f8 to your computer and use it in GitHub Desktop.
Spring Boot Open Feign Client Integration Testing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
test: | |
url: | |
url: http://localhost:${server.port} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.springframework.boot.SpringApplication; | |
import org.springframework.boot.autoconfigure.SpringBootApplication; | |
import org.springframework.cloud.openfeign.EnableFeignClients; | |
import org.springframework.context.ApplicationContextInitializer; | |
import org.springframework.context.ConfigurableApplicationContext; | |
import org.springframework.core.env.MapPropertySource; | |
import org.springframework.util.SocketUtils; | |
import java.util.HashMap; | |
import java.util.Map; | |
@SpringBootApplication | |
@EnableFeignClients | |
public class TestApplication { | |
public static void main(String... args) { | |
SpringApplication.run(TestApplication.class, args); | |
} | |
public static class TestApplicationInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> { | |
@Override | |
public void initialize(ConfigurableApplicationContext applicationContext) { | |
Map<String, Object> properties = new HashMap<>(); | |
properties.put("server.port", SocketUtils.findAvailableTcpPort()); | |
MapPropertySource propertySource = new MapPropertySource("Random Defined Server Port", properties); | |
applicationContext.getEnvironment().getPropertySources().addFirst(propertySource); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Testing Open Feign Clients With Spring Boot | |
Here is an alternative method for testing feign clients with randomly assigned server ports. | |
With this approach, no load balancer configuration is required. | |
Please note, that instead of `WebEnvironment.RANDOM_PORT` one has to use the `WebEnvironment.DEFINED_PORT`. | |
See the attached sources for more information. | |
## Some Background Information | |
While using `RANDOM_PORT` as the web environment to use with a `SpringBootTest` works just fine with the embedded server, e.g. | |
``` | |
@SpringBootTest(classes = TestApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) | |
``` | |
The random port is assigned by Java NIO, which uses a native method to find an unused random port. | |
To achieve this, spring will set the server.port environment variable to 0. | |
And, as soon as the web server started, the port will be known and it will then be set as the `local.server.port` | |
environment variable, which then can be injected via for example `@LocalServerPort`. | |
The feign client configuration, especially the url, will have been initialized long before that, so the feign client | |
will use whatever value `server.port` was assigned to. | |
Existing methods of injecting the random server port into the feign client configuration mostly involve setting up a | |
ribbon configuration and similar such mechanisms. (see https://medium.com/swlh/spring-boot-how-to-unit-test-a-feign-client-in-isolation-using-only-service-name-4e0fc9e151a7) | |
These methods, however use the ribbon package which is soon to be deprecated as it gets replaced by other load balancers | |
such as eureka or the spring loadbalancer. | |
Also, for setting up a quick and dirty test these methods all require additional configuration overhead. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.springframework.cloud.openfeign.FeignClient; | |
import org.springframework.web.bind.annotation.GetMapping; | |
@FeignClient(name = "test", contextId = "test", url = "${test.url}", path = "/test") | |
public interface TestWebClient { | |
@GetMapping(value = "/", produces = "text/plain") | |
String hello(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.junit.jupiter.api.Test; | |
import org.springframework.beans.factory.annotation.Autowired; | |
import org.springframework.boot.test.context.SpringBootTest; | |
import org.springframework.boot.web.server.LocalServerPort; | |
import org.springframework.core.env.Environment; | |
import org.springframework.test.context.ContextConfiguration; | |
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) | |
@ContextConfiguration(classes = TestApplication.class, initializers = TestApplication.TestApplicationInitializer.class) | |
public class TestWebClientTest { | |
@Autowired | |
private TestWebClient webClient; | |
@LocalServerPort | |
private int port; | |
@Autowired | |
private Environment environment; | |
@Test | |
public void notatest() throws Exception { | |
System.out.println(port); | |
System.out.println(webClient.hello()); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.springframework.web.bind.annotation.GetMapping; | |
import org.springframework.web.bind.annotation.RestController; | |
import org.springframework.web.bind.annotation.ResponseBody; | |
@RestController | |
@RequestMapping(value = "/test") | |
public class TestWebService | |
@GetMapping(value = {"", "/"}, produces = "text/plain") | |
@ResponseBody | |
public String hello() { | |
return "world"; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment