2
votes

Impossible de simuler RestTemplate dans Spring Boot-Junit 5-Mockito

J'essaie de simuler un modèle de repos dans ma classe DAO mais Mockito lance une erreur étrange disant qu'il ne peut pas se moquer.

Essayer de couvrir les cas de test unitaires pour mon application Spring Boot version 2.x. J'ai presque essayé toutes les solutions possibles sur Internet, comme la mise à jour de JDK / JRE pour la compilation, mais je suis coincé avec l'erreur suivante:

gradlew test

Voici mon code: p >

build.gradle

gradlew bootRun

MyDao.java

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

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 pour RestTemplate

@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;
        });
    }
}

Toutes les suggestions seront vraiment utiles

PS: L'application fonctionne parfaitement grâce à la commande 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()
}

Le problème vient uniquement des tests unitaires

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)
....


0 commentaires

3 Réponses :


2
votes

L'une des causes du problème décrit (ou subordonné) pourrait être, puisque RestTemplate n'est ni "privé" ni "final" et "dit mockable", l'invocation / la dérision de restTemplate.getForEntity ()

... dans le version actuelle , cette méthode est disponible en trois versions / avec des paramètres de surcharge:

  • ... getForEntity (String url, Classe responseType, Object ... uriVariables) ...
  • ... getForEntity (String url, Classe responseType, Map uriVariables) ...
  • ... getForEntity (url URI, classe responseType) ...

Dans votre code (opérationnel), vous semblez utiliser la 1ère saveur, donc sans le changer (le code opérationnel), je propose d'ajuster votre code de test à:

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

Mais le message d'erreur me rend toujours "prudent" et je me demande ... vous êtes à la pointe de la pile junit (5), êtes-vous confiant concernant votre configuration de test !? (libs / config gradle manquant?)

S'il vous plaît, "essayez":

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

pas:

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

.. comme indiqué sur dzone's spring-boot-2-with-junit-5-and-mockito-2-for-unit . Si cela (et d'autres conclusions du didacticiel) ne vous aide pas, pensez à vraiment:

le signaler à la liste de diffusion (.)


Et j'ai entendu / lu la première fois (de ma vie):

simuler un modèle de repos dans ma classe DAO

Pensez à nommer votre dao comme "service" (+ les étapes / refactorings correspondants;)


0 commentaires

1
votes

D'accord, j'ai résolu le problème. C'était une incompatibilité de version entre les jars mockito-core et mockito-junit-jupiter, ce qui posait problème.

La dépendance correcte est:

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

Auparavant, c'était

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'

Gradle choisissait la dernière version de mockito-core jar car il lui était demandé de choisir n'importe quelle version de la série 2.x, comme défini dans le fichier de construction. Je pense que le reste est explicite.

Heureux, tests unitaires! : P


0 commentaires

1
votes

Ce problème m'est arrivé parce que j'exécutais par inadvertance Java 11. Une fois que je suis passé à Java 8, qui est standard pour le projet, le problème a disparu.


0 commentaires