Problems with null pointer using mockito - java

I'm trying to test a method. And in this method, a new Object is instancied, but I don't want it, otherwise other class will be tested.
How I tell to mockito dont intanciate it?
#Component
#EnableScheduling
public class VerificadorDeNovasAssinaturas {
private DocuSign docuSign;
private ApiClient apiClient;
#Autowired
private DocuSignProperties docuSignProperties;
public EnvelopesInformation verificaNovasAssinaturas() throws Exception {
this.docuSign = new DocuSign(docuSignProperties); // I don't want mockito instanciate DocuSign
this.apiClient = docuSign.getApiClient();
this.apiClient.addDefaultHeader("Authorization", "Bearer " + docuSign.getoAuthToken().getAccessToken());
And my test class:
#SpringBootTest
#RunWith(SpringRunner.class)
#ActiveProfiles("test")
public class VerificadorDeNovasAssinaturasTest {
#InjectMocks
private VerificadorDeNovasAssinaturas verificador;
private DocuSignProperties docuSignProperties;
private ApiClient apiClient;
private UserInfo userInfo;
private OAuthToken oAuthToken;
#Mock
private DocuSign docuSign;
#Before
public void initialize() throws Exception {
docuSignProperties = new DocuSignProperties();
docuSignProperties.setBaseUrl("https://demo.docusign.net/restapi");
docuSignProperties.setBasePath("/restapi");
setApiClientConfigurations();
when(docuSign.getApiClient()).thenReturn(this.apiClient);
when(docuSign.getoAuthToken()).thenReturn(this.oAuthToken);
...}
private void setApiClientConfigurations() throws Exception {
this.apiClient = new ApiClient(this.docuSignProperties.getBaseUrl());
this.oAuthToken = getOAuth();
... }
#Test
public void testaVerificacaoDeNovasAssinaturas() throws Exception {
EnvelopesInformation results = verificador.verificaNovasAssinaturas();
assertNotNull(results);
}
I don't want mockito instanciate a new DocuSign, because this is not the reason of the test. There is some way do ignore this step?

Well, Mockito can not change something if your code( Code to be tested, Which you intend to) does something, However you can mock it so that it does not create a new object (rather have your "Mocked Object"), so that you can verify something against the expected behavior.
In your code if you change few lines , you can achieve what you want, like -
Create a DocuSignService class and there you create this new object in say some - getDocuSign method. Then your code looks something like below -
#Autowired
private DocuSignService docuSignService ;
this.docuSign = new DocuSign(docuSignProperties); // This is what you have
this.docuSign = this.docuSignService.getDocuSign() ; // This is new code
Now in your test case -
#Mock
DocuSignService docuSignService ;
#Mock
private DocuSign docuSign;
//.
//.
Mockito.when(this.docuSignService.getDocuSign()).thenReturn(docuSign);
Now you have control on this object.

I resolved it using powerMockito.
DocuSign docuSign = PowerMockito.mock(DocuSign.class);
PowerMockito.whenNew(DocuSign.class).withAnyArguments().thenReturn(docuSign);

Related

initialise a service for mocking in java with mockito and junit 5

I'm trying to learn some integration testing whilst creating a project to make a game database, and have got a class that calls a service within it's methods
public DigitalGame findDigitalGameByTitleAndPlatform(DigitalGame digitalGame){
if(digitalGame == null){
return null;
}
return GamesJPAService.iDigitalGameRepository.findDigitalGameByTitleAndPlatform(digitalGame.getTitle(), digitalGame.getPlatform());
}
The GamesJpaService as shown below, is initialised as an #Service when the project is started as an application. But is not initialised within the test class, no matter whether it is autowired,newed up, or any other method I have spotted to try and initialise it. for example using the #InjectMocks annotation
#Service
public class GamesJPAService implements IJpaServices {
public static IDigitalGameRepository iDigitalGameRepository;
#Autowired
private IDigitalGameRepository iDigitalGameRepo;
#PostConstruct
public void init(){
iDigitalGameRepository = this.iDigitalGameRepo;
}
}
The IDigitalGameRepository that it calls looks like:
public interface IDigitalGameRepository extends JpaRepository<DigitalGame, String> {
DigitalGame findDigitalGameByTitleAndPlatform(String title, Platform platform);
}
I have ommited some methods from the proceeding code. My test class also looks like (at the moment)
#DisplayName("Digital Games Dao Test")
class DigitalGamesDaoTest {
Set<Peripheral> compatiblePeriphs = new HashSet<>();
Set<SupportedLanguages> supportedLanguages = new HashSet<>();
List<Mods> mods = new ArrayList<>();
List<DLC> dlc = new ArrayList<>();
DigitalGame olliolli = new DigitalGame("olliolli", "", "sports", "olliolli", new ReleaseDate(), new Platform(), compatiblePeriphs, new Developer(), new Publisher(), new Region(), supportedLanguages, new NoneEnglish(), mods, dlc, "", new SpecialEdition(), true, new Platform());
private IDigitalGamesDao digitalGamesDao;
#Mock
GamesJPAService gamesJpaService;
#BeforeEach
void setUp() {
digitalGamesDao = new DigitalGamesDao();
}
#Test
#DisplayName("insertDigitalGame should return false when digital game already in database")
public void insertDigitalGameShouldReturnFalseWhenDigitalGameInDatabase(){
EntityManager mockEntityManager = mock(EntityManager.class);
when(GamesJPAService.iDigitalGameRepository.findDigitalGameByTitleAndPlatform(olliolli.getTitle(), olliolli.getPlatform())).thenReturn(olliolli);
doReturn(olliolli).when(digitalGamesDao.findDigitalGameByTitleAndPlatform(olliolli));
when(digitalGamesDao.findDigitalGameByTitleAndPlatform(olliolli)).thenReturn(olliolli);
when(mockEntityManager.merge(olliolli)).thenReturn(null);
assertFalse(digitalGamesDao.insertDigitalGame(olliolli));
}
#Test
#DisplayName("insertDigitalGame should return true when digital game added to database")
public void insertDigitalGameShouldReturnTrueWhenDigitalGameNotInDatabase(){
}
and I am getting a null pointer exception,
java.lang.NullPointerException: Cannot invoke "com.me.gamedatabasebackend.dao.gamesJPA.IDigitalGameRepository.findDigitalGameByTitleAndPlatform(String, com.me.gamedatabasebackend.model.platform.Platform)" because "com.me.gamedatabasebackend.dao.gamesJPA.GamesJPAService.iDigitalGameRepository" is null
As GamesJPAService is not being tested I need to know how to skip it and just return the value. So I need help to find a way for either, doing a component scan from my test class, or importing the GamesJPAService into it in a useable manner.
You need to annotate your test class with some think like that to make injection works
#ExtendWith(SpringExtension.class)
#ContextConfiguration(classes = { SpringTestConfiguration.class })
DisplayName("Digital Games Dao Test")
class DigitalGamesDaoTest {
...
But you have a nullpointer because GamesJPAService.iDigitalGameRepository is null. That's a static property and the instance of GamesJPAService is a mock so the init() method is never call.

How to write unit test for URI create in java

Below is the method I'm trying to write unit test using junit 5
#Value("${proxy.host}")
private String endpoint;
public Request<Void> setAwsRequestGETParameter(String setStatusPath) {
Request<Void> requestAws = new DefaultRequest<Void>("sts");
requestAws.setHttpMethod(HttpMethodName.GET);
requestAws.setEndpoint(URI.create(endpoint));
requestAws.setResourcePath(setStatusPath);
return requestAws;
}
Below is the unit test I'm trying to run
#InjectMocks
private AWSAuthHandler testAWSAuthHandler;
#Test
public void testSetAwsRequestGETParameter() throws Exception {
URI mockedURI = Mockito.mock(URI.class);
assertNotNull(testAWSAuthHandler.setAwsRequestGETParameter("/status/7deaed5e-3080-45ec-89ba-403977d60c0c"));
}
Below is the stack trace:
java.lang.NullPointerException
at java.base/java.net.URI$Parser.parse(URI.java:3106)
at java.base/java.net.URI.<init>(URI.java:600)
at java.base/java.net.URI.create(URI.java:881)
Can someone please help me with the missing part? Thank you
For setting properties of class that you can't mock you can use Spring Reflection Utils, like that:
ReflectionUtils.setField(field, target, value);
where the field is the name of the field which you want to set ("endpoint" for your case),
target is the mocked class (testAWSAuthHandler for your case)
value is the wanted value
As Sweta Sharma said, you need to initialise AWSAuthHandler with some value for endpoint field. That's why it is better to use constructor injection rather than field one.
Assuming your AWSAuthHandler class look like this (as you didn't provide the code for the whole class):
public class AWSAuthHandler {
#Value("${proxy.host}")
private String endpoint;
public Request<Void> setAwsRequestGETParameter(String setStatusPath) {
Request<Void> requestAws = new DefaultRequest<Void>("sts");
requestAws.setHttpMethod(HttpMethodName.GET);
requestAws.setEndpoint(URI.create(endpoint));
requestAws.setResourcePath(setStatusPath);
return requestAws;
}
You can refactor it in the following way:
public class AWSAuthHandler {
private String endpoint;
public AWSAuthHandler(#Value("${proxy.host}") String endpoint) {
this.endpoint = endpoint;
}
public Request<Void> setAwsRequestGETParameter(String setStatusPath) {
Request<Void> requestAws = new DefaultRequest<Void>("sts");
requestAws.setHttpMethod(HttpMethodName.GET);
requestAws.setEndpoint(URI.create(endpoint));
requestAws.setResourcePath(setStatusPath);
return requestAws;
}
Then you can create tests for this class:
private AWSAuthHandler testAWSAuthHandler;
#BeforeEach
void setUpTests() {
this.testAWSAuthHandler = new AWSAuthHandler("some-endpoint-here");
}
#Test
public void testSetAwsRequestGETParameter() throws Exception {
assertNotNull(testAWSAuthHandler.setAwsRequestGETParameter("/status/7deaed5e-3080-45ec-89ba-403977d60c0c"));
}
You can read more about Spring #Value annotation here, for example: https://www.baeldung.com/spring-value-annotation

Value passed to argumentMatchers.eq() appears null

I'm mocking a method getQuizFromQuizResponse that requires a non-null object. I tried using eq() from the ArgumentMatchers library to pass in an existing object I initialized. When I debug SecurityServiceTest in my IDE, eq(quizResponse) appears exactly how I intend it to. When I reach a breakpoint in the method I'm mocking, getQuizFromQuizResponse(), quizResponse then appears as null.
Why doesn't eq() keep the value I defined when mocking?
For further context:
[OUTDATED] the class of the method I am attempting to mock, QuizMapper, is a Spy. I mention this because I feel this could be why I'm having this issue?
[OUTDATED] The reason I have QuizMapper as a Spy is because we did not create this class to be a bean since it's purpose is to simply map from DTO to another... so it isn't a Service.
[OUTDATED] Since QuizMapper isn't a bean I couldn't autowire it or inject it into SecurityService and attempting to make it a #Mock would have mockito giving me error like so: "Strict stubbing argument mismatch"
I now have QuizMapper as a #Mock because I realized that in verifyUser() I'm calling on a builder which is causing the argument mismatch to have some initialized data which I believe goes against stubbing?
Here's the error:
org.mockito.exceptions.misusing.PotentialStubbingProblem:
Strict stubbing argument mismatch. Please check:
- this invocation of 'checkIdentity' method:
feignClient.checkIdentity(
0L,
null,
Verification(type=Initiate, settings=Settings(mode=null,
reference=Reference1, locale=en_US, venue=online), persons=.
[Person(name=null, addresses=[], ssn=null, phones=null,
emails=null, context=primary, Id=Id)], answers=null)
);
-> at com.*.Service.verifyUser(SecurityService.java:39)
- has following stubbing(s) with different arguments:
1. feignClient.checkIdentity(
0L,
null,
null
);
Here's my code:
#ExtendWith(MockitoExtension.class)
class SecurityServiceTest {
#InjectMocks
private SecurityService securityService;
#Spy
private FeignClient feignClient;
#Spy
private QuizMapper quizMapper;
#Test
void testVerifyUserReturnsQuiz() throws ProviderException {
String id = "Id";
String mode = "test";
Quiz expectedQuiz = new Quiz();
expectedQuiz.setId("quizId");
Verification verification = new VerificationBuilder()
.setType(VerificationBuilder.TYPE)
.setMode(mode)
.setId(id)
.build();
QuizResponse quizResponse = new QuizResponse();
quizResponse.setProducts(new ProductTestUtil().getProductList());
given(
feignClient.checkIdentity(any(Long.class), any(String.class), eq(verification))
).willReturn(singleQuizResponse);
given(
quizMapper.getQuizFromQuizResponse(eq(quizResponse))
).willReturn(expectedQuiz);
Quiz actualQuiz = securityService.verifyUser(id);
assertEquals(actualQuiz, expectedQuiz);
}
}
Here is the class and function I am trying to invoke in my unit test
#Slf4j
#Service
public class SecurityService {
private final FeignClient feignClient;
#Value(“${mode}")
private String settingsMode;
#Value("${accountId}")
private long accountId;
#Value("${workflowName}")
private String workflowName;
public SecurityService(FeignCleint feignClient) {
this.feignClient = feignClient;
}
public Quiz verifyUser(String lexId) throws ProviderException {
QuizMapper quizMapper = new QuizMapper();
Verification user = new VerificationBuilder()
.setType(VerificationBuilder.TYPE)
.setMode(mode)
.setId(Id)
.build();
logger.info("Verification POST request: {}", user);
QuizResponse response = feignClient.checkIdentity(accountId, workflowName, user);
logger.info("QuizResponse POST response: {}", response);
return quizMapper.getQuizFromQuizResponse(response);
}
}

Test the service in springboot

This is the service I have :
#Service
public class UserInfoService {
#Autowired
private UserInfoServiceClient UserInfoServiceClient; // Call another Rest API
public ResponseEntity<ResponseUserInfoData> sendUserInfo(String UserId) throws RuntimeException {
ResponseUserInfoData responseUserInfoData = new ResponseUserInfoData();
//Get the body from the User service client
UserServiceDTO UserServiceDTO = UserInfoServiceClient.sendResponse(UserId).getBody();
//Set the values of responseUserInfoData
Optional<UserServiceDTO> UserServiceDTOOptional = Optional.ofNullable(UserServiceDTO);
if (UserServiceDTOOptional.isPresent()) {
UserServiceDTOOptional.map(UserServiceDTO::getId).ifPresent(responseUserInfoData::setid);
}
else return ResponseEntity.noContent().build();
}
}
I have to test it. I'm new to JUnit testing. I want to test the following points:
To check if the service return the response entity
To check if the get and set method works
This is what I started?
#RunWith(MockitoJUnitRunner.class)
public class ServiceTests {
#InjectMocks
private UserInfoService UserInfoService;
#Mock
private UserInfoServiceClient UserInfoServiceClient;
#Mock
private UserServiceDTO UserServiceDTO;
#Test
public void shouldReturnUserInfoData() throws IOException{
UserInfoService.sendUserInfo("ABC");
}
}
Any help is appreciated?
Mockito is useful to mock the dependencies of the service so that you can test all the code path in you service. In your case you will want to stub the call to serInfoServiceClient.sendResponse(UserId) and have it return a specific UserServiceDTO for each test case.
The test file looks like it is set up correctly, you only need to mock the method to give you the result you need for the particular test, for example
#RunWith(MockitoJUnitRunner.class)
public class ServiceTests {
#InjectMocks
private UserInfoService UserInfoService;
#Mock
private UserInfoServiceClient UserInfoServiceClient;
#Test
public void shouldReturnUserInfoData() throws IOException{
final String userId = "123";
// The mocked return value should be set up per test scenario
final UserServiceDto dto = new UserServiceDto();
final ResponseEntity<UserServiceDTO> mockedResp = new ResponseEntity<>(dto, HttpStatus.OK);
// set up the mock service to return your response
when(UserInfoServiceClient.sendResponse(userId)).thenReturn(mockedResp);
// Call your service
ResponseEntity<ResponseUserInfoData> resp = UserInfoService.sendUserInfo(userId);
// Test the result
Assert.isNotNull(resp);
}
}
There are also other ways to mock the dependencies using Mockito. I suggest going through the quick start of https://site.mockito.org/

Mocked class recognized as 'static member' is being called but it is not being recognized in the test as the mock?

I've mocked the class and it is till giving me this error. Not sure what I'm doing wrong here but I get the error: when() requires an argument which has to be 'a method call on a mock' on the line that contains
Mockito.when(trdi.strToInteger(newValueIn)).thenReturn(0);
The class is mocked, but I don't understand why it's giving me this error. My IDE is also telling me that trdi.strToInteger is a static member being accessed via instance reference.
public class TestApproved extends TestGroovy {
#Mock
private DataLayer dl;
#Mock
private DataStore dsIn;
#Mock
private DataStore ds;
#Mock
private TRDIUtils trdi;
#Parameterized.Parameter
public String client;
#Parameterized.Parameters(name = "{index}: {0}")
public static Object[] data() {
return new Object[]{
1, 2, 3, 4
};
}
private String newValueIn;
#Before
public void setUp() throws Exception {
//groovy script file to test
groovyScriptFile = new File(GROOVY_SCRIPTS_FOLDER + "/" + client + "/ToTest.groovy");
MockitoAnnotations.initMocks(this);
newValueIn = "1";
//groovy script parameters
addGroovyBindingVariable(GroovyScriptArgName.DATASTORE, dsIn);
addGroovyBindingVariable(GroovyScriptArgName.NEW_VALUE, newValueIn);
}
/**
* Test that user and date are nullified/disallowed to be updated if 'Approved' column is unchecked
*
*/
#Test
public void testUncheckedApproved() throws Exception{
Mockito.when(trdi.strToInteger(newValueIn)).thenReturn(0);
evaluate();
Mockito.verify(dsIn, Mockito.times(1)).setItemNull(1,"XX_APPROV_DATE");
Mockito.verify(dsIn, Mockito.times(1)).setItemNull(1,"XX_APPROV_USER");
}
For mocking static classes we need to use PowerMockito.
Use the following call to prepare you static class methods for mocking
PowerMockito.mockStatic(TRDIUtils.class)
Then start using your methods as the following
PowerMockito.when(TRDIUtilsstrToInteger(newValueIn)).thenReturn(0);
Hope this helps to customise it for your own logic. Happy coding.

Categories