As part of TDD i want to be able to test every portion of my SpringBoot rest application. However i am unable to mock external calls.
Application structure
1. Few rest endpoints which internally call external rest endpoints.
2. All calls to external endpoints are orchestrated through a local http client which utilizes RestTemplate as httpClient.
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.MOCK, classes = TestDrivenDevelopmentWithJavaApplication.class)
public class TestDrivenDevelopmentWithJavaApplicationTests {
@Autowired
private WebApplicationContext webApplicationContext;
private MockMvc mockMvc;
@MockBean
private RestTemplate client;
@Before
public void setup() throws Exception {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
Structure1Root category = new Structure1Root();
Category cat = new Category();
cat.setCategoryName("Test1");
cat.setDescription("Test");
category.setD(cat);
Mockito.when(client.exchange(
ArgumentMatchers.eq("https://services.odata.org/V2/Northwind/Northwind.svc/Products(1)?$format=json"),
ArgumentMatchers.eq(HttpMethod.GET), ArgumentMatchers.eq(null),
ArgumentMatchers.eq(Structure1Root.class)))
.thenReturn(new ResponseEntity<Structure1Root>(category, HttpStatus.OK));
}
@Test
public void testendpoint1() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/api/endpoint1?token=1").contentType(MediaType.APPLICATION_JSON))
.andExpect(content().string(org.hamcrest.Matchers.containsString("Test1")));
}
}
Even though i have setup the mock on client.exchange(RestTemplate.exchange), i see response returned by client.exchange is null and not the response specified in thenReturn
Controller Code
@RestController
@RequestMapping(path = Endpoint.base)
public class Endpoint {
public static final String base = "/api";
@Autowired
MyHttpClient<Structure2Root> client;
@Autowired
MyHttpClient<Structure1Root> Cclient;
@GetMapping(path = "/endpoint1")
public ResponseEntity<Structure2Root> callEndpt1(@RequestParam String token) {
Response<Structure2Root> resp = client
.execute("https://services.odata.org/V2/Northwind/Northwind.svc/Products(1)?$format=json", Structure2Root.class);
return new ResponseEntity<Structure2Root>(resp.getResponse(), HttpStatus.OK);
}
@GetMapping(path = "/endpoint2")
public ResponseEntity<Structure1Root> callEndpt2(@RequestParam String token) {
Response<Structure1Root> resp = Cclient.execute(
"https://services.odata.org/V2/Northwind/Northwind.svc/Categories(1)?$format=json", Structure1Root.class);
return new ResponseEntity<Structure1Root>(resp.getResponse(),HttpStatus.OK);
}
}
And finally, local http client code
@Service
public class MyHttpClient<O> {
@Autowired
RestTemplate client;
public MyHttpClient() {
// TODO Auto-generated constructor stub
}
public Response<O> execute(String url, Class<O> generic) {
ResponseEntity<O> resp = client.exchange(url, HttpMethod.GET, null, generic);
return new Response<O>(resp.getStatusCode(), resp.getBody());
}
}
this client.execute
is what i intend to intercept in the first code block
However never seems to work and always returns a null. The Git Repo
Regards,
Veera