Дразнить шаблон отдыха весной - PullRequest
0 голосов
/ 26 февраля 2019

Я пытаюсь проверить моего клиента весеннего отдыха, но у меня проблемы.Вот мой класс клиента:

@Component
public class MyClient{    

    private RestTemplate restTemplate;


    @Autowired
    public MyClient(RestTemplateBuilder restTemplateBuilder,ResponseErrorHandler myResponseErrorHandler) {
        this.restTemplate = restTemplateBuilder
                .errorHandler(myResponseErrorHandler)
                .build();
    }
    //other codes here
}

здесь myResponseErrorHandler - это класс, который переопределяет handleError и hasError методы ResponseErrorHandler класса.

Теперь мой тестовый класс имеет вид

    @RunWith(SpringRunner.class)
    public class MyClientTest {    

        @InjectMocks
        MyClient myClient;
        @Mock
        RestTemplate restTemplate;
        @Mock
        RestTemplateBuilder restTemplateBuilder;

       //test cases here
    }

Но я получаю сообщение об ошибке, как показано ниже, и я не уверен, как это исправить.

You haven't provided the instance at field declaration so I tried to construct the instance.
However the constructor or the initialization block threw an exception : null

Ответы [ 3 ]

0 голосов
/ 28 февраля 2019

У вас есть хороший пример для смоделированного автосопровождения с зависимостями,

В вашем случае вам нужно также смоделировать ResponseErrorHandler:

@RunWith(MockitoJUnitRunner.class)
public class MyClientTest {

@Mock
private ResponseErrorHandler responseErrorHandler ;

@Mock
private RestTemplateBuilder restTemplateBuilder ;

private MyClient myClient;

@Before
void setUp() {
    myClient = new MyClient(restTemplateBuilder ,responseErrorHandler );
}
0 голосов
/ 03 марта 2019

Эта проблема заключается в том, что при нормальном запуске приложения Spring Boot автоматически настраивает RestTemplateBuilder для вас (из-за аннотации @SpringBootApplication), но в тесте у вас нет соответствующей аннотации @SpringBootTest и * 1004.* в конструкторе MyClient, конечно, null (который выдает ошибку при попытке вызвать для него метод build ()).

Если вы добавите его как есть, он будет использовать контекст конфигурации приложения по умолчанию, и оба RestTemplateBuilder и MyResponseErrorHandler будут рабочими bean-компонентами (обратите внимание, что в этом случае MyClient и MyResponseErrorHandler должны быть настроены как bean-компоненты - например, пометив их @Component).

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

    @Autowired
    private MyClient myClient;

    @Mock
    private MyResponseErrorHandler myResponseErrorHandler;

    @Test
    public void sampleTest() throws IOException {
        //The example of configuring myResponseErrorHandler behavior
        Mockito.when(myResponseErrorHandler.hasError(Mockito.any())).thenReturn(true);

        //Call myClient method

        //Asserts...
    }
}

Кроме того, ничего не делайте с RestTemplate, потому что он будет создан программно внутри конструктора MyClient.

Другой подход заключается в создании отдельной тестовой конфигурации, где вы можете получитьbean-компонент по умолчанию RestTemplateBuilder (предоставляется Spring) и mocked MyResponseErrorHandler (для настройки его поведения позже).Это может дать вам полный контроль над настройкой всех ваших bean-компонентов для тестов без использования контекста вашего приложения.

Если вы хотите в этом разобраться - вот шаги для достижения этого:

  1. Создание класса конфигурации теста с MyResponseErrorHandler bean:
@TestConfiguration
public class MyClientTestConfiguration {

    @Autowired
    private RestTemplateBuilder restTemplateBuilder;

    @Bean
    public ResponseErrorHandler myResponseErrorHandler() {
        return Mockito.mock(MyResponseErrorHandler.class);
    }


    @Bean
    public MyClient myClient() {
        return new MyClient(restTemplateBuilder, myResponseErrorHandler());
    }
}
Ваш тестовый класс будет таким:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MyClientTestConfiguration.class)
public class MyClientTest {

    @Autowired //wired from MyClientTestConfiguration class
    private MyClient myClient;

    @Autowired //wired from MyClientTestConfiguration class
    private MyResponseErrorHandler myResponseErrorHandler; 

    @Test
    public void sampleTest() throws IOException {
        //The example of configuring myResponseErrorHandler behavior
        Mockito.when(myResponseErrorHandler.hasError(Mockito.any())).thenReturn(true);

        //Calling myClient method...

        //Asserts...
    }
}
0 голосов
/ 26 февраля 2019
@Component
public class MyClient{    

private RestTemplate restTemplate;


@Autowired
public MyClient(RestTemplateBuilder restTemplateBuilder,ResponseErrorHandler myResponseErrorHandler) {
    this(restTemplateBuilder
            .errorHandler(myResponseErrorHandler)
            .build());
}

MyClient(RestTemplate template) {
    this.restTemplate = template;
}
//other codes here
}

Этот пример ниже, когда работает нормально.Изменить для использования SpringRunner.class.

открытый класс MyClientTest {

   private MyClient myClient;
   @Mock private RestTemplate restTemplate;

   @Before
   public void setUp() throws Exception {
       MockitoAnnotations.initMocks(this);
       myClient = new MyClient(restTemplate);
   }

   //test cases here
}
...