我有一个静态类,该类将进入另一个项目,以获取我的应用程序启动时所需的信息,因为该项目具有多个子项目,而其他项目则需要这些信息进行处理,因此我必须使其静态并因为我只希望一个实例存在于跨项目中,所以我将构造函数设为私有,因此当其他项目需要此信息列表时,他们只能使用此类class.getinstance()。getList()来获取所有信息,这将迫使其他项目使用相同的信息列出跨子项目。我确实想尝试将此类放在Web服务项目中,然后可以使用Autowired完成所有操作,但是问题出在其他子项目中,他们不能接受Autowired跨项目,因此它使信息列表成为了我只能在Web服务项目中访问该类,该类位于实用程序项目中,因此在我的Web服务项目中,我有一个用于初始化该类的服务,并且该类仅应初始化一次,因此我给它提供了一个带有获取实例方法,因此Web服务类将在此类中调用配置方法以对其进行初始化,并且还使用restTemplate运行Web服务调用以收集所需的信息,因此该类上方没有服务类,现在我想为了测试该类,我使用springRunner对它进行了一次模拟测试,但似乎没有达到我的模拟数据。
我尝试了几种在google上找到的解决方案,它们似乎都与我的情况稍有不同,它们@InjectMocksof服务类并模拟RestTemplat,但是我的情况它不需要服务类,并且由于其私有构造函数,我可以也不要注入它。
这是我位于Utilities项目中的班级。
public class InfoBook
{
//private constructor and config method to set username password and endpoint etc
protected Info LoadInfo()
{
final RestTemplate restTemplate = new RestTemplate();
final HttpHeaders headers = new HttpHeaders();
headers.setBasicAuth(username, password);
final HttpEntity<String> request = new HttpEntity<>(headers);
ResponseEntity<List<InfoResource>> response = null;
try
{
response = restTemplate.exchange(wsEndPoint,
HttpMethod.GET, request, new ParameterizedTypeReference<List<InfoResource>>()
{
});
}
catch (final RestClientException e)
{
//Catch Exception if anything happened during make the rest request, such as connection refused etc.
}
Info info = null;
if (response != null)
{
final List<InfoResource> informationList = response.getBody();
info = InformationMapper.INSTANCE.inforResourceToInfo(informationList.get(0));
}
return info ;
}
}
这是我进行的测试:
@RunWith(SpringRunner.class)
public class InfoBookTest
{
@Mock
private RestTemplate restTemplate;
@Before
public void setUp()
{
InfoBook.configInstance("username", "password", "http://localhost:8080");
List<InfoResource> informationList = new ArrayList<>();
InfoResource infoResource = new InfoResource();
// Set content
informationList.add(infoResource);
ResponseEntity<List<InfoResource>> response = new ResponseEntity<>(informationList, HttpStatus.OK);
Mockito.when(restTemplate.exchange(ArgumentMatchers.any(URI.class),
ArgumentMatchers.any(HttpMethod.class), ArgumentMatchers.<HttpEntity<String>> any(),
ArgumentMatchers.<Class<List<InfoResource>>> any())).thenReturn(response);
}
@Test
public void testloadInfo()
{
final Info info=
InfoBook.getInstance().loadInfo();
Assert.assertEquals(1000, info.getInfoId());
}
}
现在,如果我运行了此测试,它将尝试对localhost:8080进行Web服务调用,并且当然会得到连接拒绝错误。它似乎并没有击中我的Mockito,然后返回。 有人可以告诉我如何嘲笑吗?
谢谢
答案 0 :(得分:0)
您的课程有一个RestTemplate的最终字段,它使用一个新的真实RestTemplate
进行初始化。实际上,您没有接缝可进行测试,因此目前尚不可能。您将需要在InfoBook
中添加一个字段和设置器,可以从测试中调用它,或者更好的是使InfoBook成为服务,并使用bean和自动装配的字段。 InfoBook不再是一个单例,但是Spring无论如何都只会创建一个,因此它实际上是一个单例,只是没有static getInstance()
,需要在使用的所有地方进行自动装配。
@Service
public class InfoBook {
@Autowired
private RestTemplate restTemplate;
//private constructor and config method to set username password and endpoint etc
protected Info LoadInfo() {
final HttpHeaders headers = new HttpHeaders();
headers.setBasicAuth(username, password);
final HttpEntity<String> request = new HttpEntity<>(headers);
ResponseEntity<List<InfoResource>> response = null;
try {
response = restTemplate.exchange(wsEndPoint,
HttpMethod.GET, request, new ParameterizedTypeReference<List<InfoResource>>() {
});
} catch (final RestClientException e) {
//Catch Exception if anything happened during make the rest request, such as connection refused etc.
}
Info info = null;
if (response != null) {
final List<InfoResource> informationList = response.getBody();
info = InformationMapper.INSTANCE.inforResourceToInfo(informationList.get(0));
}
return info;
}
}
您需要一个配置类来创建RestTemplate
bean
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder){
return restTemplateBuilder.build();
}
}
最后,您可以仅使用Mockito运行程序进行测试,并且需要使用@InjectMocks
创建InfoBook。
@RunWith(MockitoJUnitRunner.class)
public class InfoBookTest
{
@InjectMocks
private InfoBook infoBook;
@Mock
private RestTemplate restTemplate;
...
答案 1 :(得分:0)
好吧,这是非常愚蠢的,我认为我最好只是回答自己的问题,以便处于相同或相似情况的某人可以获得一些帮助,我如何解决我的问题是我应该将InfoBook类中的restTemplate移到方法之外并给出它是一个get和set方法,在我的测试中,我应该只设置我的模拟restTemplate,然后一切都将被正确模拟,所以不是我使用真正的restTemplate,而是应该使用我的模拟对象,这就是为什么它们不同而我模拟的原因数据未返回。
感谢所有提供帮助的人。