0

I want to configure Spring feign with a configuration class, and I want to make sure that all the @Bean methods are called when Spring configures the feign client for me.

How to test it?

For example, I have:

@FeignClient(
        name = "PreAuthSendRequest",
        url = "${xxx.services.preauth.send.url}",
        configuration = AppFeignConfig.class)
public interface RequestService {
    @PostMapping("")
    @Headers("Content-Type: application/json")
    PreAuthResponse execute(@RequestBody PreAuthRequest preAuthRequest);
}

And AppFeignConfig.java:

@Configuration
@RequiredArgsConstructor
public class AppFeignConfig{

    private final HttpClient httpClient;
    private final Jackson2ObjectMapperBuilder contextObjectMapperBuilder;

    @Bean
    public ApacheHttpClient client() {
        return new ApacheHttpClient(httpClient);
    }

    @Bean
    public Decoder feignDecoder() {
        return new JacksonDecoder((ObjectMapper)contextObjectMapperBuilder.build());
    }

    @Bean
    public Encoder feignEncoder() {
        return new JacksonEncoder((ObjectMapper)contextObjectMapperBuilder.build());
    }

    @Bean
    public Retryer retryer() {
        return Retryer.NEVER_RETRY;
    }


    @Bean
    public ErrorDecoder errorDecoder() {
        return new ServiceResponseErrorDecoder();
    }
}

So, how to verify that all @Bean methods are called? I know @MockBean, but what I want to check is config.feignDecoder(), etc., are indeed called.

When I am trying to context.getBean(RequestService.class); and call execute() method, it seems to send a real request and without wiremock, it fails, obviously.

WesternGun
  • 11,303
  • 6
  • 88
  • 157
  • That seems a lot like testing the specific implementation and the framework. What's the *behaviour* you want to test? – jonrsharpe Jul 01 '19 at 13:05
  • So you mean, this is implementation related and not to do with behaviour? Or, this part, getting the correct bean, is not meant to test? – WesternGun Jul 01 '19 at 13:07
  • I feel that putting a log message (with DEBUG level) inside each of those methods would be a good way to ensure that they are called (instead of testing them) – ali4j Jul 01 '19 at 13:56
  • Yes @ali4j this could also be a good solution. I am considering this but I don't know; the overhead of redirecting the stdout to a file and check that has been done some times in this project. Maybe. – WesternGun Jul 01 '19 at 14:07
  • @jonrsharpe I must say that I agree with you to some extent, I kind of think that it should be part of integration tests but I am not sure, still confused about behaviour tests and unit tests... – WesternGun Jul 01 '19 at 14:24

1 Answers1

-2

For now I have this:

@SpringBootTest
@ExtendWith(SpringExtension.class)
@ActiveProfiles("test")
class RequestServiceTest {

    @Autowired
    private ApplicationContext applicationContext;

    @MockBean
    private ApacheHttpClient client;

    @MockBean
    private Decoder feignDecoder;

    @MockBean
    private Encoder feignEncoder;

    @MockBean
    private Retryer retryer;

    @MockBean
    private ErrorDecoder errorDecoder;

    @Test
    void shouldRetrieveBeansFromApplicationContextToConstructConfigurationInstance() {
        AppFeignConfig config = applicationContext.getBean(AppFeignConfig.class);
        Assertions.assertEquals(config.feignEncoder(), feignEncoder);
        Assertions.assertEquals(config.feignDecoder(), feignDecoder);
        Assertions.assertEquals(config.errorDecoder(), errorDecoder);
        Assertions.assertEquals(config.client(), client);
        Assertions.assertEquals(config.retryer(), retryer);
    }

}

I don't know if it is how it should be. If any idea, please comment.

WesternGun
  • 11,303
  • 6
  • 88
  • 157