如何将 RestTemplate 注入另一个 class 并进行测试?

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

我目前有这样的服务class:

@Service
public class CarService {
    private RestTemplate restTemplate;

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

应用程序运行器正在调用它 class,如下所示:

@Component
public class CarRunner implements ApplicationRunner {

    @Autowired
    CarService carService;

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

我想摆脱 restTemplate = new RestTemplate(); 因为它在我模拟测试时给我带来了问题。

我的测试 class 是这样的:

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

避免这种依赖的最佳方法是什么?

使用构造函数注入代替字段注入,如下所示:

@Service
public class CarService {
    private RestTemplate restTemplate;

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

Spring 将理解创建 CarService 需要一个 RestTemplate bean,并将通过构造函数注入它(假设您在别处创建了一个 RestTemplate bean,最有可能通过自动配置)。

然后在测试中,可以去掉new CarService();如下:

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