4

I have a test for a Feign client and I would like to set up a test slice, like @WebMvcTest, @DataJpaTest, etc.

For example, the following test uses @SpringBootTest and it loads all the application context:

@SpringBootTest
@AutoConfigureWireMock(port = 0)
class AgePredictorFeignClientTest {

    @Autowired
    private AgePredictorFeignClient agePredictorFeignClient;

    @Test
    void getAge() {
        stubFor(get(urlEqualTo("/age-api?name=Henrique"))
                .willReturn(aResponse().withBodyFile("25_years_old.json")
                        .withHeader("Content-Type", "application/json")));

        Integer age = agePredictorFeignClient.getAge("Henrique").getAge();

        assertThat(age).isEqualTo(25);

        verify(getRequestedFor(urlEqualTo("/age-api?name=Henrique")));
    }
}

How could I change this test to load only the context related to Spring Cloud OpenFeign?

The source code for the application with this test is available at https://github.com/henriquels25/openfeign-tests-sample.

henriquels
  • 518
  • 4
  • 20

2 Answers2

5

Currently there is no out of the box solution to have something like a @FeignTest. However, somebody made a solution for this to be found here. This solution Adds the desired functionality. It also has been proposed to spring-cloud-openfeign.

If you don't want to include the above depedency, I've created an example by manually importing some AutoConfiguration classes to only load necessary functionality. See here for a Feign client under test using this Test configuration

The only down-side of this, is that the wiremock random port can't expanded in time. That's why it has a fixed port.

Nazeem
  • 746
  • 1
  • 10
  • 29
  • sensational and exactly that worked here – Pedro Bacchini Mar 24 '23 at 20:13
  • @Nazeem Thanks so much for the needed Feign configuration imports. Thanks to you I got it to work. It can work with random port though. I posted an answer providing a custom test slice to show how. – I.Brok Apr 04 '23 at 17:36
  • @I.Brok, nice to see that I could of be any help! Good that you got the random port working. I am aware of setting port to zero, however, when I ran the full test suite, for some reason it didn't expanded the random value in time. Maybe it has now changed with updates to either wiremock and/or feign. – Nazeem Apr 05 '23 at 12:32
0

Thanks to the answer of Nazeem who provided me with the correct Configurations to import for Feign Clients I created the following test slice, which works well for me.

Option with random port:

Java:

@Target(ElementType.TYPE)
@Retention(RUNTIME)
@SpringBootTest
@AutoConfigureWireMock(port = 0)
@Import(TestFeignConfiguration.class)
public @interface FeignTest {

  @AliasFor(annotation = SpringBootTest.class, attribute = "classes")
  Class<?>[] classes() default {};
}

Kotlin:

@Target(CLASS)
@Retention(RUNTIME)
@SpringBootTest
@AutoConfigureWireMock(port = 0)
@Import(TestFeignConfiguration::class)
annotation class FeignTest (

  @get:AliasFor(annotation = SpringBootTest::class, attribute = "classes")
  val classes: Array<KClass<*>> = emptyArray()
)

With FeignTestConfiguration:

@TestConfiguration
@EnableFeignClients()
@Import(value = [FeignAutoConfiguration::class, JacksonAutoConfiguration::class, HttpMessageConvertersAutoConfiguration::class])
class TestFeignConfiguration

In your test simply use @FeignClient([YourFeignClient::class]) (kotlin, probably .class for Java)

By setting port to 0, it will be set randomly.

To set the random port for you urls you can simply configure the url in your configuration. For example:

clients:
  yourFeignClient:
    url: http://localhost:${wiremock.server.port}

Alternatively for a fixedPort, you could replace @AutoConfigureWireMock(port = 0) with another port or use @WireMockTest(httpPort = 9099) for example

I.Brok
  • 319
  • 1
  • 2
  • 16