0

我有一个静态类,它将转到另一个项目,在我的应用程序启动时获取我需要的信息,因为这个项目有多个子项目,而其他项目需要这些信息来处理,所以我必须使它成为静态的,因为我只有想要一个实例存在跨项目,我将构造函数设为私有,所以当其他项目需要这个信息列表时,他们只能使用这个 class.getinstance().getList() 来获取所有信息,这将强制其他项目使用相同的信息列表交叉子项目。我确实想过尝试将这个类放在Web服务项目中,然后一切都可以用Autowired完成,但问题是在其他子项目中,他们无法接受Autowired跨项目,所以它制作了我的信息列表收集的只能在 Web 服务项目中访问,此类位于实用程序项目中,

我已经尝试了几种我在谷歌上找到的解决方案,似乎它们都与我的情况略有不同,他们@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 时然后返回。谁能告诉我我怎么能嘲笑这个?

谢谢

4

2 回答 2

0

你的类有一个 RestTemplate 的 final 字段,它用一个新的、真实的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;
    }
}

您需要一个配置类来创建RestTemplatebean

@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;
...
于 2019-05-23T03:40:11.010 回答
0

好的,这很愚蠢,我想我最好只回答我自己的问题,以便处于相同或类似情况的人可以获得一些帮助,我解决问题的方法是我应该将 InfoBook 类中的 restTemplate 移到方法之外并给它一个 get并设置方法,在我的测试中,我应该只设置我的模拟restTemplate,然后一切都会被正确模拟,所以我应该使用我的模拟的而不是使用真正的restTemplate,这就是为什么它们不同而我的模拟数据不是回来。

感谢所有帮助过的人。

于 2019-05-23T17:37:00.727 回答