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));
...
}
}