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)
....
3 Réponses :
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;)
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
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.