从单元测试运行内容时,@ Value解析为空

时间:2019-02-16 16:08:58

标签: spring junit mockito

我有以下服务类别:

@Service
public class BidServiceImpl implements BidService {

    private final String apiUrl;

    private final RestTemplate restTemplate;

    @Autowired
    public BidServiceImpl(RestTemplate restTemplate,
                          @Value("${api.url}") String apiUrl){
        this.apiUrl = apiUrl;
        this.restTemplate = restTemplate;
    }


    public List<Bid> findAll() {
        ResponseEntity<Bid[]> responseEntity = restTemplate.getForEntity(apiUrl, Bid[].class);
        Bid[] bids = responseEntity.getBody();
        return Arrays.asList(bids);
    }
}

以及随后的测试:

@RunWith(MockitoJUnitRunner.class)
public class TestBidService {

    @InjectMocks
    private BidServiceImpl bidService;

    @Mock
    RestTemplate restTemplate;

    @Test
    public void testFindAllReturnsListOfBids(){
        List<Bid> b = new ArrayList<>();
        Bid[] arr = new Bid[2];
        arr[1] = new Bid();
        arr[0] = new Bid();
        ResponseEntity<Bid[]> br = new ResponseEntity<>(arr, HttpStatus.OK);
        when(restTemplate.getForEntity("url",Bid[].class)).thenReturn(br);
        List<Bid> bids = bidService.findAll();
        Assert.assertEquals(2,bids.size());
        Assert.assertTrue(bids instanceof List);
    }
}

运行单元测试时,我在NullPointerException上得到了apiUrl。在我的服务类中作为@Value注入。问题是为什么当我运行api并通过控制器访问该服务方法时,它无法从application.properties中获取值,所以一切正常。

1 个答案:

答案 0 :(得分:1)

因为所有<?php $DBhost = "localhost"; $DBuser = "root"; $DBpass = ""; $DBname = "test"; try{ $DBcon = new PDO("mysql:host=$DBhost;dbname=$DBname",$DBuser,$DBpass); $DBcon->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); }catch(PDOException $ex){ die($ex->getMessage()); } ?> @MockitoJUnitRunner@InjectMocks都是Mockito的东西,他们对Spring一无所知。因此,他们不了解@Mock所做的事情,也不会注入其价值。在这种情况下,弹簧容器甚至不会启动。

如果您正在使用spring-boot并希望Spring注入该值,则可以考虑使用@Value起动器并使用其spring-boot-starter-test来配置Mockito模拟:

@MockBean

但这是一个集成测试,因为它将启动整个spring容器,因此它比真正的单元测试要慢。

如果您希望测试尽可能快地运行,请不要依赖Spring为您注入该值。只需自己设置:

@RunWith(SpringRunner.class)
@SpringBootTest
public class TestBidService { 

    @Autowired
    private BidServiceImpl bidService;

    @MockBean
    RestTemplate restTemplate;

    @Test
    public void testFindAllReturnsListOfBids(){
       ///
    }
}