springspring-bootspring-boot-testspring-cloud-feignnetflix-feign

How can I test a my rest controller that has feign clients?


I have a rest controller that is using 2 fein clients, I want to write and test the Rest controller with different samples, I am not an expert at writing springboot tests.

In this scenario I have no repositories to test with, just feign clients accessed through a rest controller. Below is my testing controller code

@RestController
public class CustomerController {

    @Autowired
    private CustomerClient customerClient;

    @Autowired
    private PaymentsClient paymentsClient;

    @RequestMapping(path = "/getAllCustomers", method = RequestMethod.GET)
    public ResponseEntity<Object> getAllCustomers() {
        List<Customer> customers = customerClient.getAllCustomers();
        return new ResponseEntity<>(customers, HttpStatus.OK);

    }

    @RequestMapping(path = "/{customerId}", method = RequestMethod.GET)
    public ResponseEntity<Object> get(@PathVariable() long customerId) {
        try {
            Customer c = customerClient.getCustomerById(customerId);
            if (c != null) {
                return new ResponseEntity<>(c, HttpStatus.OK);
            } else {
                return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Customer Not Found");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
        }
    }

    @RequestMapping(path = "/{customerId}", method = RequestMethod.PATCH)
    public ResponseEntity<Object> UpdateCustomer(@PathVariable() Long customerId, @RequestBody Customer customer) {
        Customer c;
        try {
            c = customerClient.update(customerId, customer);
            if (c != null) {
                return new ResponseEntity<>(c, HttpStatus.OK);
            } else {
                return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Customer Not Found");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
        }
    }

    @RequestMapping(path = "", method = RequestMethod.POST)
    public ResponseEntity<Object> saveCustomer(@RequestBody Customer customer) {
        Customer c;
        try {
            c = customerClient.saveCustomer(customer);
            return new ResponseEntity<>(c, HttpStatus.OK);
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
        }
    }

    @RequestMapping(path = "/registerPayment", method = RequestMethod.POST)
    public ResponseEntity<Object> saveCustomer(@RequestBody Payment payment) {
        Payment p = null;
        Customer c = null;
        try {
            c = customerClient.getCustomerById(payment.getCustomerId());
            p = paymentsClient.saveCustomer(payment);
            return new ResponseEntity<>(p, HttpStatus.OK);
        } catch (Exception e) {
            if (null == c) {
                return ResponseEntity.status(HttpStatus.UNPROCESSABLE_ENTITY).body("Customer Does not Exist");
            } else {
                e.printStackTrace();
                return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
            }
        }
    }

Most of the tests I have seen have a repository injected in but for my case I dont have those, just fein clients, Im I doing it wrong,

Below is my current test

@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles("test")
public class CustomerControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @InjectMocks
    private CustomerController customerController;

    @Before
    public void setup() {

        mockMvc = MockMvcBuilders.standaloneSetup(customerController).build();
    }

    @Test
    public void getAllCustomers() {

        try {
            this.mockMvc.perform(get("/getAllCustomers")).andExpect(status().isOk())
                    .andExpect(content().json("[{\n" + "    \"customerId\": 24,\n"
                            + "    \"firstName\": \"Benjamin\",\n" + "    \"secondName\": \" Masiga\",\n"
                            + "    \"email\": \"ben@ben.com\"\n" + "  }"));
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

I'm getting the error below,

NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.test.web.servlet.MockMvc' available: expected at least 1 bean which qualifies as autowire candidate. 

Solution

  • Its as simple as writing any other JUnit test.

    @RunWith(SpringRunner.class)
    @SpringBootTest
    @ActiveProfiles("test")
    public class CustomerControllerTest {
    
        @Mock
        private CustomerClient customerClient;
    
        @InjectMocks
        private CustomerController customerController;
    
        @Test
        public void getAllCustomers() {
            List<Customer> customers = new ArrayList<>();
            customers.add(new Customers("name"));
            Mockito.when(customerClient.getAllCustomers()).thenReturn(customers);
            Mockito.assertEquals(customers.toString(),customerController.getAllCustomers())
        }
    
    }