Good afternoon, I'm currently developing a microservice with Quarkus and Grpc. I'm implementing Mockito for testing and I get the following error:
[INFO] Running com.tmve.customer.service.ValidateNumberActivationGrpcServiceTest
15:18:38 INFO traceId=, parentId=, spanId=, sampled= [co.tm.cu.se.ValidateNumberActivationGrpcService] (main) Excepcion en la capa Service:Cannot invoke "com.tmve.customer.mapping.ValidateNumberActivationResMapper.mapResultStoreProcedureToResponse(java.util.HashMap)" because "this.mappper" is null
This is the class I'm trying to mock
package com.tmve.customer.service;
import com.cies.grpc.proto.ValidateNumberActivationReply;
import com.cies.grpc.proto.ValidateNumberActivationRequest;
import com.tmve.customer.oracle.repository.EventRepository;
import com.tmve.customer.util.CustomLogger;
import io.quarkus.test.junit.QuarkusTest;
import io.smallrye.mutiny.Uni;
import .junit.jupiter.api.BeforeEach;
import .junit.jupiter.api.Test;
import .mockito.InjectMocks;
import .mockito.Mock;
import .mockito.MockitoAnnotations;
import .mockito.junit.jupiter.MockitoExtension;
import java.util.HashMap;
import static .junit.jupiter.api.Assertions.assertEquals;
import static .junit.jupiter.api.Assertions.assertNotNull;
import static .mockito.ArgumentMatchers.any;
import static .mockito.Mockito.when;
@QuarkusTest
public class ValidateNumberActivationGrpcServiceTest {
@InjectMocks
private ValidateNumberActivationGrpcService grpcService;
@Mock
private EventRepository eventRepository;
@Mock
private CustomLogger customLogger;
@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
/*request = ValidateNumberActivationRequest.newBuilder()
.setMsisdn("145869997")
.build(); */
}
@Test
void findValidateNumberActivation_Success() {
ValidateNumberActivationRequest request = buildValidateNumberActivationRequest();
HashMap<String,String> map = new HashMap<>();
map.put("status","OC");
map.put("statusDate","25/12/24");
map.put("registerDate","21/09/06");
map.put("reason","El numero tiene estado de validación");
when(eventRepository.findValidateNumberStatus(any(ValidateNumberActivationRequest.class)))
.thenReturn(map);
Uni<ValidateNumberActivationReply> responseUni=grpcService.validateNumberActivationStatus(request);
ValidateNumberActivationReply reply=responseUni.await().indefinitely();
assertNotNull(reply);
assertEquals("OC", reply.getMsisdnStatus());
assertEquals("25/12/24", reply.getStatusDate());
assertEquals("21/09/06", reply.getRegistrationDate());
assertEquals("El numero tiene estado de validación", reply.getReason());
}
private ValidateNumberActivationRequest buildValidateNumberActivationRequest() {
return ValidateNumberActivationRequest.newBuilder().setMsisdn("145869997").build();
}
}
This is my service layer class and where the error is exploding:
ValidateNumberActivationGrpcService
package com.tmve.customer.service;
import com.cies.grpc.proto.MutinyValidateNumberActivationGrpcGrpc;
import com.cies.grpc.proto.ValidateNumberActivationReply;
import com.cies.grpc.proto.ValidateNumberActivationRequest;
import com.google.gson.Gson;
import com.tmve.customer.mapping.ValidateNumberActivationResMapper;
import com.tmve.customer.oracle.repository.EventRepository;
import com.tmve.customer.util.CustomLogger;
import com.tmve.customer.util.LogMessage;
import com.tmve.customer.exceptions.handlergrpc.GrpcExceptionHandler;
import io.quarkus.grpc.GrpcService;
import io.smallryemon.annotation.Blocking;
import io.smallrye.mutiny.Uni;
import io.smallrye.mutiny.unchecked.Unchecked;
import jakarta.inject.Inject;
import lombok.extern.slf4j.Slf4j;
import java.util.HashMap;
@Slf4j
@GrpcService
public class ValidateNumberActivationGrpcService extends MutinyValidateNumberActivationGrpcGrpc.ValidateNumberActivationGrpcImplBase{
@Inject
public EventRepository eventRepository;
@Inject
public ValidateNumberActivationResMapper mappper;
@Inject
CustomLogger customLogger;
private final Gson gson= new Gson();
@Override
@Blocking
public Uni<ValidateNumberActivationReply> validateNumberActivationStatus(ValidateNumberActivationRequest request) {
customLogger.logInfo(this, LogMessage.GRPC_REQUEST_RECEIVED.getMessage(), request);
/*requestValidator.validateNumberActivationRequest(request) */
return Uni.createFrom().item(Unchecked.supplier(() -> {
try {
customLogger.logInfo(this, LogMessage.DATABASE_OPERATION_STARTED.getMessage(), request);
HashMap<String, String> map = eventRepository.findValidateNumberStatus(request);
customLogger.logInfo(this, LogMessage.DATABASE_OPERATION_COMPLETED.getMessage());
ValidateNumberActivationReply reply=mappper.mapResultStoreProcedureToResponse(map);
String jsonResponse = gson.toJson(reply);
customLogger.logInfo(this, "Response MS con FindMissing Event: " + jsonResponse);
return reply;
} catch (Exception e) {
log.info("Excepcion en la capa Service:{}", e.getMessage());
throw GrpcExceptionHandler.handleException(e);
}
}));
}
}
ValidateNumberActivationResMapperImpl
package com.tmve.customer.mapping.impl;
import com.cies.grpc.proto.ValidateNumberActivationReply;
import com.tmve.customer.mapping.ValidateNumberActivationResMapper;
import com.tmve.customer.util.CustomLogger;
import com.tmve.customer.util.LogMessage;
import com.tmve.customer.exceptions.MappingException;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import lombok.extern.slf4j.Slf4j;
import java.util.HashMap;
@Slf4j
@ApplicationScoped
public class ValidateNumberActivationResMapperImpl implements ValidateNumberActivationResMapper {
@Inject
public CustomLogger logger;
@Override
public ValidateNumberActivationReply mapResultStoreProcedureToResponse(HashMap<String,String> map) {
ValidateNumberActivationReply.Builder replyBuilder=ValidateNumberActivationReply.newBuilder();
logger.logInfo(this, LogMessage.MAPPING_RESPONSE_STARTED.getMessage());
try {
replyBuilder.setMsisdnStatus(cleanString(map.get("status")));
replyBuilder.setStatusDate(cleanString(map.get("statusDate")));
replyBuilder.setRegistrationDate(cleanString(map.get("registerDate")));
replyBuilder.setReason(cleanString(map.get("reason")));
logger.logInfo(this, LogMessage.MAPPING_RESPONSE_COMPLETED.getMessage());
} catch (Exception e) {
log.error("Error execute mapping {}", e.getMessage());
logger.logError(this, LogMessage.MAPPING_ERROR.getMessage(), e);
throw new MappingException("Error during mapping", e);
}
return replyBuilder.build();
}
public String cleanString(String input) {
if (input == null) {
return "";
}
return input.replaceAll("[\\u0000-\\u001F\\u007F]", "").trim();
}
}
When testing my functionality everything is ok, the problem occurs when I go to run the tests and it fails when injecting the ValidateNumberActivationResMapperImpl class into the ValidateNumberActivationGrpcService, why could this be happening?
This is my pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns=".0.0" xmlns:xsi="; xsi:schemaLocation=".0.0 .0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>.tmve.customer</groupId>
<artifactId>validate-number-activation</artifactId>
<version>1.0.0-DEV</version>
<properties>
<compiler-plugin.version>3.13.0</compiler-plugin.version>
<mavenpiler.release>17</mavenpiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
<quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
<quarkus.platform.version>3.19.2</quarkus.platform.version>
<skipITs>true</skipITs>
<surefire-plugin.version>3.5.2</surefire-plugin.version>
<!-- sonar -->
<sonar.projectKey>validate-number-activation</sonar.projectKey>
<sonar.projectName>validate-number-activation</sonar.projectName>
<sonar.sources>src/main/java</sonar.sources>
<sonar.tests>src/test/java</sonar.tests>
<sonar.java.binaries>target/classes</sonar.java.binaries>
<sonar.java.test.binaries>target/test-classes</sonar.java.test.binaries>
<sonar.coverage.jacoco.xmlReportPaths>target/jacoco-report/jacoco.xml</sonar.coverage.jacoco.xmlReportPaths>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>${quarkus.platform.group-id}</groupId>
<artifactId>${quarkus.platform.artifact-id}</artifactId>
<version>${quarkus.platform.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-grpc</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jdbc-oracle</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest-jackson</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-orm</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-opentelemetry</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry.instrumentation</groupId>
<artifactId>opentelemetry-jdbc</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-grpc-common</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jacoco</artifactId>
</dependency>
<dependency>
<groupId>.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.34</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.11.0</version>
</dependency>
<dependency>
<groupId>.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.4.0</version>
</dependency>
<dependency>
<groupId>.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
</dependency>
<dependency>
<groupId>.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-openapi</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-swagger-ui</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-fault-tolerance</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-health</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>${quarkus.platform.group-id}</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${quarkus.platform.version}</version>
<extensions>true</extensions>
<executions>
<execution>
<goals>
<goal>build</goal>
<goal>generate-code</goal>
<goal>generate-code-tests</goal>
<goal>native-image-agent</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>${compiler-plugin.version}</version>
<configuration>
<parameters>true</parameters>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire-plugin.version}</version>
<configuration>
<systemPropertyVariables>
<java.util.logging.manager>.jboss.logmanager.LogManager</java.util.logging.manager>
<maven.home>${maven.home}</maven.home>
</systemPropertyVariables>
</configuration>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${surefire-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
<configuration>
<systemPropertyVariables>
<native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>
<java.util.logging.manager>.jboss.logmanager.LogManager</java.util.logging.manager>
<maven.home>${maven.home}</maven.home>
</systemPropertyVariables>
</configuration>
</plugin>
<plugin>
<groupId>.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>4.0.0.4121</version>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>native</id>
<activation>
<property>
<name>native</name>
</property>
</activation>
<properties>
<skipITs>false</skipITs>
<quarkus.native.enabled>true</quarkus.native.enabled>
</properties>
</profile>
</profiles>
</project>