Как я делаю замену ResteTemplate без обслуживания - PullRequest
0 голосов
/ 22 мая 2019

У меня есть статический класс, который пойдет в другой проект и получит информацию о том, что мне нужно, когда мое приложение запускается, так как этот проект имеет несколько подпроектов, и другие проекты нуждаются в этой информации для процесса, поэтому я должен сделать его статическим иПоскольку я хочу, чтобы только один экземпляр существовал между проектами, я сделал конструктор закрытым, поэтому, когда другим проектам нужен этот информационный список, они могут использовать только этот class.getinstance (). getList (), чтобы получить всю информацию, это заставит другой проект использовать ту же информацию.список кросс-подпроектов.Я подумал о том, чтобы попробовать поставить этот класс в проект веб-службы, тогда все можно сделать с помощью Autowired, но проблема в другом подпроекте, они не могли принять кросс-проекты Autowired, поэтому он создал информационный список.Собранный только может быть доступ в рамках проекта веб-службы, этот класс находится в проекте утилиты, поэтому в моем проекте веб-службы у меня есть служба для инициализации этого класса, и этот класс должен быть инициализирован только один раз, поэтому я даю ему частный конструктор сполучить экземпляр метода, поэтому класс веб-службы вызовет метод конфигурации в этом классе для его инициализации, а также запустит вызов веб-службы с restTemplate для сбора необходимой мне информации, поэтому у этого класса нет класса службы над ним, теперь я хотел быЧтобы протестировать этот класс, я сделал тест на мокито для него с помощью SpringRunner, но, похоже, он не влияет на мои насмешливые данные.

Я пробовал несколько решений, которые я нашел с помощью Google, и кажется, что все они немного отличаются от моей ситуации, они@InjectMocksof service class и макет 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, и, конечно, он получает ошибку соединения отказано.Кажется, это не ударил мой Mockito, когда и затем возврат.Может кто-нибудь сказать мне, как я мог издеваться над этим?

спасибо

Ответы [ 2 ]

0 голосов
/ 23 мая 2019

хорошо, это очень глупо, я подумал, что лучше просто ответить на свой вопрос, чтобы кто-то в такой же или похожей ситуации мог получить некоторую помощь, как я могу решить мою проблему, я должен переместить restTemplate в классе InfoBook за пределы метода и дать это метод get and set, в моем тесте я должен просто установить свой mock restTemplate, тогда все будет правильно смоделировано, так что вместо того, чтобы использовать реальный restTemplate, я должен использовать мой mock, поэтому они отличались, а мои - данные не были возвращены.

спасибо всем, кто помог.

0 голосов
/ 23 мая 2019

У вашего класса есть последнее поле RestTemplate, которое он инициализирует новым, и реальным RestTemplate. Фактически у вас нет швов для тестирования, поэтому в настоящее время это невозможно. Вам нужно будет добавить поле и установщик в InfoBook, который вы можете вызвать из своего теста или, что еще лучше, сделать InfoBook сервисом и использовать объект EJB и поле с автопроводкой. 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;
...
...