简体   繁体   中英

Mock Feign client in Spring controller in integration test

I have a gateway controller that uses internally different services. I try to write integration test that mock feign client for the controller but it doesn't work as I expected.

I have the following Feign client:

public interface StoreManagementClient {
    @RequestLine("GET /v1/stores/{storeId}")
    @Headers({"Accept: application/json", "Content-Type: application/json;charset=UTF-8"})
    StoreDetails getStoreDetails(@Param("storeId") String storeId);
}

Store controller:

@Validated
@Controller
@RequestMapping("${gateway.path}")
public class StoreController {

    @Autowired
    private StoreManagementClient storeManagementClient;

    @GetMapping(value = "/stores/{storeId}", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<StoreDetails> getStoreDetails(
            @PathVariable("storeId") String storeId) {
        StoreDetails details = storeManagementClient.getStoreDetails(storeId);
        return ResponseEntity.ok(details);
    }
}

And the integration test:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {GatewayServiceApplication.class},
        webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public class ClientIntegrationTest {
    @Autowired
    private StoreController storeController;

    @MockBean
    private StoreManagementClient storeManagementClient;

    private MockClient mockClient;

    @Before
    public void setUp() throws Exception {
        mockClient = new MockClient();
    }

    @Test
    public void testCorrectGetStoreDetailsRequest() throws JsonProcessingException {

        String storeId = "store-1";

        StoreDetails storeDetails = new StoreDetails();
        storeDetails.setId(storeId);
        storeDetails.setType("grocery");

        String response = new ObjectMapper().writeValueAsString(storeDetails);

        storeManagementClient = Feign.builder()
                .encoder(new JacksonEncoder())
                .decoder(new JacksonDecoder())
                .client(mockClient
                        .ok(RequestKey.builder(feign.mock.HttpMethod.GET, "/v1/stores/" + sroreId)
                                .headers(ImmutableMap.of(
                                        ACCEPT, newArrayList("application/json"),
                                        CONTENT_TYPE, newArrayList("application/json;charset=UTF-8"))).build(),
                                response
                        ))
                .target(new MockTarget<>(StoreManagementClient.class));

        // when
        ResponseEntity<StoreDetails> result = storeController.getStoreDetails(storeId);

        // then
        StoreDetails resultBody = result.getBody();

        assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK);
        assertThat(resultBody.getId()).isEqualTo(storeId);
        assertThat(resultBody.getType()).isEqualTo("grocery");
}

I suppose that test should mock response according the described Feign Client. But actually it returns null .

Should I do something wrong with mocking Feign client? Probably, I mixed in one test testing Feign client and my own controller and I need to separate it and write unit-test for Feign client like Mock Feign Client example ? I would be appreciate any advice

First, you replace feign client StoreManagementClient by mock:

@MockBean
private StoreManagementClient storeManagementClient;

Then in test you lost reference to the mock and points to local object:

storeManagementClient = Feign.builder()....build();

but controller still use the mock

In Plain java, you do something like:

Client client = new Client(null);
Controller controller = new Controller(client);
client = new Client(1);
assertThat(controller.get()).isEqualTo(1)) // no no no: is equal to null

PS. I hope in future my answer will be constructive

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM