Невозможно смоделировать RestTemplate в SpringBoot-Junit5-Mockito - PullRequest
0 голосов
/ 07 февраля 2019

Я пытаюсь смоделировать шаблон отдыха в своем классе DAO, но Mockito выдает странную ошибку, говоря, что не умеет имитировать.

Пытаюсь покрыть примеры модульных тестов для моего весеннего загрузочного приложения версии 2.Икс.Я почти перепробовал все возможные решения через Интернет, такие как обновление JDK / JRE для компиляции, но я застрял со следующей ошибкой:

org.mockito.exceptions.base.MockitoException: 
Mockito cannot mock this class: class org.springframework.web.client.RestTemplate.

Mockito can only mock non-private & non-final classes.
If you're not sure why you're getting this error, please report to the mailing list.


Java               : 1.8
JVM vendor name    : Oracle Corporation
JVM vendor version : 25.181-b13
JVM name           : Java HotSpot(TM) 64-Bit Server VM
JVM version        : 1.8.0_181-b13
JVM info           : mixed mode
OS name            : Windows 10
OS version         : 10.0


Underlying exception : java.lang.IllegalArgumentException: Could not create type
    at org.mockito.junit.jupiter.MockitoExtension.beforeEach(MockitoExtension.java:115)
....

Ниже приведен мой код:

build.gradle

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter'
    implementation 'org.springframework.boot:spring-boot-starter-data-rest'
    implementation 'org.springframework.retry:spring-retry'
    implementation 'org.aspectj:aspectjrt'
    implementation 'org.aspectj:aspectjweaver'
    implementation 'org.springframework:spring-aop'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'

    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.2.0'
    testCompile 'org.junit.jupiter:junit-jupiter-params:5.2.0'
    testRuntime 'org.junit.jupiter:junit-jupiter-engine:5.2.0'
    testImplementation 'org.mockito:mockito-core:2.+'
    testImplementation 'org.mockito:mockito-junit-jupiter:2.18.3'
}

test {
    testLogging.showStandardStreams = true
    useJUnitPlatform()
}

MyDao.java

@Repository
public class MyDao {    
    @Value("${app.prop.service.url}")
    private String url;

    @Autowired
    public RestTemplate restTemplate;

    public String getSignals() {
        System.out.println("url -----------------------> " + url);
        return new RetryTemplate().execute(context -> {
            ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);

            if (response.getStatusCodeValue() == 200) {
                System.out.println("Server response -> " + response.getBody());
                return response.getBody();
            } else {
                throw new RuntimeException("server response status: " + response.getStatusCode());
            }
        }, context -> {
            System.out.println("retry count: " + context.getRetryCount());
            System.err.println("error -> " + context.getLastThrowable());
            return null;
        });
    }
}

MyDaoTest.java

@ExtendWith(MockitoExtension.class)
public class MyDaoTest {    
    @Mock
    private RestTemplate restTemplate;

    @InjectMocks
    private MyDao dao;

    @BeforeEach
    public void prepare() {
        ResponseEntity<String> response = new ResponseEntity<>("{name: myname}", HttpStatus.OK);
        Mockito.doReturn(response).when(restTemplate.getForEntity(Mockito.anyString(), String.class));
    }

    @Test
    public void testGetSignals() {
        System.out.println("------------------TEST-------------------");
        String result = dao.getSignals();
        System.out.println("result ------>" + result);
        assertEquals("{name: myname}", result);
    }
}

BeanConfig для RestTemplate

@Bean
public RestTemplate restTemplate() {
    // block of code for SSL config for HTTPS connection
    return new RestTemplate();
}

Любые предложения будут действительнополезно

PS: приложение отлично работает с помощью команды gradle

gradlew bootRun

Проблема только в модульном тестировании

gradlew test

Ответы [ 2 ]

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

Хорошо, я решил проблему.Это было несоответствие версий между банками mockito-core и mockito-junit-jupiter, что вызывало проблему.

Правильная зависимость:

testImplementation 'org.junit.jupiter:junit-jupiter-api:5.2.0'
testCompile 'org.junit.jupiter:junit-jupiter-params:5.2.0'
testRuntime 'org.junit.jupiter:junit-jupiter-engine:5.2.0'
testImplementation 'org.mockito:mockito-core:2.18.3'
testImplementation 'org.mockito:mockito-junit-jupiter:2.18.3'

Ранее это было

testImplementation 'org.mockito:mockito-core:2.+'

Gradle выбирал последнюю версию jar mockito-core, поскольку его попросили выбрать любую версию из серии 2.x, как определено в файле сборки.Я полагаю, что все остальное говорит само за себя.

Счастлив, юнит тестирование!: P

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

Одной из причин описанной (или подчиненной) проблемы может быть, поскольку RestTemplate не является ни «частным», ни «окончательным», а «известным как насмешливый», вызов / насмешка restTemplate.getForEntity()

... в текущей версии этот метод доступен в трех вариантах / с параметрами перегрузки:

  • ... getForEntity(String url, Class<T> responseType, Object... uriVariables) ...
  • ... getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables) ...
  • ... getForEntity(URI url, Class<T> responseType) ...

В вашем (рабочем) коде вы, кажется, используете первый вариант, поэтому, не меняя его (рабочий код), я предлагаю настроить ваш тестовый код так, чтобы:

...restTemplate.getForEntity(Mockito.anyString(), String.class
/*!!!*/, ArgumentMatchers.<Object>any());

См. Также:


Но сообщение об ошибке по-прежнему заставляет меня "осторожничать" и удивляться ... вы находитесь в "первоклассном" стеке junit (5), уверены ли вы в своей настройке теста !?(отсутствует gradle libs / config?)

Пожалуйста, "попробуйте":

testCompile "org.mockito:mockito-core:2.+"
testCompile('org.mockito:mockito-junit-jupiter:2.18.3')

not:

...
testImplementation 'org.mockito:mockito-core:2.+'
testImplementation 'org.mockito:mockito-junit-jupiter:2.18.3'

.. как показано на dzone's spring-boot-2-с-JUnit-5-и-Mockito-2-для-блока .Если это (и другие выводы из учебника) не помогают, подумайте:

сообщить (это) в список рассылки (.)


И я услышал / прочитал в первый раз (в моей жизни):

макет шаблон отдыха в моем DAO классе

Подумайте над именемваш дао как «сервис» (+ соответствующие шаги / рефакторинги;)

...