2.4 Creating a Client

As mentioned previously, Micronaut includes both an HTTP server and an HTTP client. A low-level HTTP client is provided out of the box which you can use to test the HelloController created in the previous section.

  1. import io.micronaut.context.annotation.Property;
  2. import io.micronaut.http.HttpRequest;
  3. import io.micronaut.http.client.HttpClient;
  4. import io.micronaut.http.client.annotation.Client;
  5. import io.micronaut.runtime.server.EmbeddedServer;
  6. import io.micronaut.test.annotation.MicronautTest;
  7. import org.junit.jupiter.api.Test;
  8. import javax.inject.Inject;
  9. import static org.junit.jupiter.api.Assertions.assertEquals;
  10. @MicronautTest
  11. public class HelloControllerSpec {
  12. @Inject
  13. EmbeddedServer server; (1)
  14. @Inject
  15. @Client("/")
  16. HttpClient client; (2)
  17. @Test
  18. void testHelloWorldResponse() {
  19. String response = client.toBlocking() (3)
  20. .retrieve(HttpRequest.GET("/hello"));
  21. assertEquals("Hello World", response); //) (4)
  22. }
  23. }
  1. import io.micronaut.http.HttpRequest
  2. import io.micronaut.http.client.HttpClient
  3. import io.micronaut.http.client.annotation.Client
  4. import io.micronaut.runtime.server.EmbeddedServer
  5. import io.micronaut.test.extensions.spock.annotation.MicronautTest
  6. import spock.lang.Specification
  7. import javax.inject.Inject
  8. @MicronautTest
  9. class HelloControllerSpec extends Specification {
  10. @Inject
  11. EmbeddedServer embeddedServer (1)
  12. @Inject
  13. @Client("/")
  14. HttpClient client (2)
  15. void "test hello world response"() {
  16. expect:
  17. client.toBlocking() (3)
  18. .retrieve(HttpRequest.GET('/hello')) == "Hello World" (4)
  19. }
  20. }
  1. import io.micronaut.context.annotation.Property
  2. import io.micronaut.http.client.HttpClient
  3. import io.micronaut.http.client.annotation.Client
  4. import io.micronaut.runtime.server.EmbeddedServer
  5. import io.micronaut.test.annotation.MicronautTest
  6. import org.junit.jupiter.api.Assertions.assertEquals
  7. import org.junit.jupiter.api.Test
  8. import javax.inject.Inject
  9. @MicronautTest
  10. class HelloControllerSpec {
  11. @Inject
  12. lateinit var server: EmbeddedServer (1)
  13. @Inject
  14. @field:Client("/")
  15. lateinit var client: HttpClient (2)
  16. @Test
  17. fun testHelloWorldResponse() {
  18. val rsp: String = client.toBlocking() (3)
  19. .retrieve("/hello")
  20. assertEquals("Hello World", rsp) (4)
  21. }
  22. }
1The EmbeddedServer is configured as a shared test field
2A HttpClient instance shared field is also defined
3The test using the toBlocking() method to make a blocking call
4The retrieve method returns the response of the controller as a String

In addition to a low-level client, Micronaut features a declarative, compile-time HTTP client, powered by the Client annotation.

To create a client, simply create an interface annotated with @Client. For example:

  1. import io.micronaut.http.MediaType;
  2. import io.micronaut.http.annotation.Get;
  3. import io.micronaut.http.client.annotation.Client;
  4. import io.reactivex.Single;
  5. @Client("/hello") (1)
  6. public interface HelloClient {
  7. @Get(consumes = MediaType.TEXT_PLAIN) (2)
  8. Single<String> hello(); (3)
  9. }
  1. import io.micronaut.http.annotation.Get
  2. import io.micronaut.http.client.annotation.Client
  3. import io.reactivex.Single
  4. @Client("/hello") (1)
  5. interface HelloClient {
  6. @Get(consumes = MediaType.TEXT_PLAIN) (2)
  7. Single<String> hello() (3)
  8. }
  1. import io.micronaut.http.MediaType
  2. import io.micronaut.http.annotation.Get
  3. import io.micronaut.http.client.annotation.Client
  4. import io.reactivex.Single
  5. @Client("/hello") (1)
  6. interface HelloClient {
  7. @Get(consumes = [MediaType.TEXT_PLAIN]) (2)
  8. fun hello(): Single<String> (3)
  9. }
1The @Client annotation is used with value that is a relative path to the current server
2The same @Get annotation used on the server is used to define the client mapping
3A RxJava Single is returned with the value read from the server

To test the HelloClient simply retrieve it from the ApplicationContext associated with the server:

  1. import io.micronaut.test.annotation.MicronautTest;
  2. import javax.inject.Inject;
  3. import org.junit.jupiter.api.Test;
  4. import static org.junit.jupiter.api.Assertions.assertEquals;
  5. @MicronautTest (1)
  6. public class HelloClientSpec {
  7. @Inject
  8. HelloClient client; (2)
  9. @Test
  10. public void testHelloWorldResponse(){
  11. assertEquals("Hello World", client.hello().blockingGet());(3)
  12. }
  13. }
  1. import io.micronaut.test.annotation.MicronautTest
  2. import spock.lang.Specification
  3. import javax.inject.Inject
  4. @MicronautTest (1)
  5. class HelloClientSpec extends Specification {
  6. @Inject HelloClient client (2)
  7. void "test hello world response"() {
  8. expect:
  9. client.hello().blockingGet() == "Hello World" (3)
  10. }
  11. }
  1. import io.micronaut.context.annotation.Property
  2. import io.micronaut.test.annotation.MicronautTest
  3. import org.junit.jupiter.api.Assertions.assertEquals
  4. import org.junit.jupiter.api.Test
  5. import javax.inject.Inject
  6. @MicronautTest (1)
  7. class HelloClientSpec {
  8. @Inject
  9. lateinit var client: HelloClient (2)
  10. @Test
  11. fun testHelloWorldResponse() {
  12. assertEquals("Hello World", client.hello().blockingGet())(3)
  13. }
  14. }
1The @MicronautTest annotation is used to define the test
2The HelloClient is injected from the ApplicationContext
3The client is invoked using RxJava’s blockingGet method

The Client annotation produces an implementation automatically for you at compile time without the need to use proxies or runtime reflection.

The Client annotation is very flexible. See the section on the Micronaut HTTP Client for more information.