Home > database >  How to inject a RestTemplate into another class and test it?
How to inject a RestTemplate into another class and test it?

Time:09-27

I currently have a service class like this:

@Service
public class CarService {
    private RestTemplate restTemplate;

    @Autowired
    public CarService () {
        restTemplate = new RestTemplate();
    }
    ...
}

that is being called by an application runner class like this:

@Component
public class CarRunner implements ApplicationRunner {

    @Autowired
    CarService carService;

    @Override
    public void run(ApplicationArguments args) throws Exception {
           ...
           Cars cars = carService.getCars();
           ...

I would like to get rid of the restTemplate = new RestTemplate(); as it is causing me problems when I'm mocking tests.

My test class is like:

@RunWith(MockitoJUnitRunner.class)
public class CarServiceTest {

    @Mock
    private RestTemplate restTemplate;

    @InjectMocks
    private CarService carService = new CarService();

    @Test
    public void testCars() {
        ...
        Mockito.when(restTemplate.exchange(
                                    RequestEntity.get(new URI(uri))
                                    .headers(headers).build(),
                                     Cars.class))
          .thenReturn(new ResponseEntity(testCars, HttpStatus.OK));
        ...
    }
}

What is the best approach to avoid this dependency?

CodePudding user response:

Instead of field injection, use constructor injection as follows:

@Service
public class CarService {
    private RestTemplate restTemplate;

    public CarService (RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }
    ...
}

Spring will understand that a RestTemplate bean is needed to create a CarService and will inject it via constructor (assuming you have a RestTemplate bean created elsewhere, most probably via auto-configuration).

Then in the test, you can remove new CarService(); as follows:

public class CarServiceTest {

    @Mock
    private RestTemplate restTemplate;

    @InjectMocks
    private CarService carService;

    @Before 
    public void initMocks() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void testCars() {
        ...
        Mockito.when(restTemplate.exchange(
                                    RequestEntity.get(new URI(uri))
                                    .headers(headers).build(),
                                     Cars.class))
          .thenReturn(new ResponseEntity(testCars, HttpStatus.OK));
        ...
    }
}
  • Related