NullPointerException in while doing mockito unit test - java

I am new to mockito Junit testing. This one is my main class which I want to test:
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
#Component
public class IlinqChecksumCalculator {
private static Logger DATA_LOADER_CHECKSUM_CALCULATOR_LOGGER = Logger.getLogger(IlinqChecksumCalculator.class);
public String calculateCheckSum(String rfsdata) throws IOException {
System.out.println(rfsdata);
String checkSumValue = null;
if (StringUtils.isNotBlank(rfsdata)) {
try {
// Create MessageDigest object for MD5
MessageDigest digest = MessageDigest.getInstance("MD5");
// Update input string in message digest
digest.update(rfsdata.getBytes(), 0, rfsdata.getBytes().length);
// Converts message digest value in base 16 (hex)
checkSumValue = new BigInteger(1, digest.digest()).toString(16);
} catch (NoSuchAlgorithmException exception) {
DATA_LOADER_CHECKSUM_CALCULATOR_LOGGER.error(
"Error in determineInputCheckSum() method during calculation of checksum for Input JSON String for ",
exception);
}
}
System.out.println("Final checksum value is:" + checkSumValue);
return checkSumValue;
}
}
This one is my test class:
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;
import java.io.IOException;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.mockito.runners.MockitoJUnitRunner;
#RunWith(MockitoJUnitRunner.class)
public class IlinqChecksumCalculatorTest {
private IlinqChecksumCalculator ilinqCheckSum;
#Before
public void setUp() throws Throwable {
MockitoAnnotations.initMocks(this);
}
#Test
public void testCheckSum() throws IOException {
when(ilinqCheckSum.calculateCheckSum("abcde")).thenReturn("defgh");
assertEquals("defgh", ilinqCheckSum.calculateCheckSum("abcde"));
}
}
I am getting a null pointer exception.

Just to answer your question: to handle ilinqCheckSum as mock, you shouuld annotate it with #Mock.
But here you should not use mockito! You want to test IlinqChecksumCalculator and not a mock! You should create a real instance of it and inject the dependendencies as mock if necessary.

By mocking calculateCheckSum method you are not covering any code in your unit test. I think you should not use Mock here. Try below test method.
public void testCheckSum() throws IOException {
String result = ilinqCheckSum.calculateCheckSum("abcde")
assertNotNull(result );
}

Related

Apache camel - I want to send to my mock endpoint

I have this test class - currently it is checking the response at the endpoint
Endpoints.SEDA_PROCESS_ENDPOINT
but I need it to check at
"mock:"+Endpoints.SEDA_PROCESS_ENDPOINT
Is there a way to forward the response to this mock endpoint I have just defined?
below is my test class
package com.sams.pricing.prism.data.processor;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import org.apache.camel.EndpointInject;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.test.spring.MockEndpoints;
import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.sams.pricing.prism.data.processor.model.CostIQRetail;
import com.sams.pricing.prism.data.processor.routes.PrismRouter;
import com.sams.pricing.prism.data.processor.service.RulesEngineClient;
import com.sams.pricing.prism.data.processor.util.Endpoints;
#SpringBootTest
#CamelSpringBootTest
#MockEndpoints( Endpoints.SEDA_PROCESS_ENDPOINT)
public class CamelRouteTests3 {
#Autowired
private ProducerTemplate template;
#EndpointInject( "mock:" + Endpoints.SEDA_PROCESS_ENDPOINT)
private MockEndpoint mock;
#Mock
private PrismRouter p;
#Mock
private RulesEngineClient rulesEngineClientMock;
public CostIQRetail costIQObject() {
CostIQRetail obj = new CostIQRetail();
obj.setItemNbr(123);
obj.setLocationNbr(4931);
obj.setIsDcFlag(false) ;
obj.setStatus("SUCCESS");
obj.setOrderableCost(new BigDecimal((10.0)));
obj.setWarehousePackCost(new BigDecimal(100.0));
obj.setOrderablePrepaidCost(null) ;
obj.setOrderableCollectCost(null) ;
obj.setReasonCode("Markdown - category funded");
obj.setEffectiveDate("2022-12-29");
obj.setIsFutureEffectiveDate(false);
obj.setCostType("WAREHOUSE PACK COST");
obj.setSource("COST IQ");
obj.setCreatedBy("lab1 account");
obj.setCreatedByUserId("LB-cost-test");
obj.setCreatedTs("2022-12-29T02:42:25.529Z");
obj.setCurrentRetailPrice(new BigDecimal(55.0)) ;
obj.setCurrentOrderableCost(null);
obj.setCurrentWarehousePackCost(new BigDecimal((0.0)));
obj.setCurrentOrderablePrepaidCost(null) ;
obj.setCurrentOrderableCollectCost(null);
obj.setMarginChange(new BigDecimal((-100.0)));
obj.setOwedToClub(new BigDecimal((0.0)));
obj.setItemSourceId(3572924);
obj.setPriceDestId(701800);
obj.setCategory(87);
obj.setOrderableQty(null);
obj.setOldMargin(new BigDecimal((100.0)));
obj.setNewMargin(new BigDecimal(0.0));
return obj;
}
private String costIQPayloadString() throws JsonProcessingException
{
String key = "{\"retailTypeReasonCode\":{\"retailTypeReasonCodeId\":{\"retailType\":\"BP\",\"retailReasonCode\":\"CC\"}},\"expirationDate\":null,\"customerRetailAmount\":0.0,\"auditMessage\":null,\"createdTimestamp\":null,\"clientID\":\"COST IQ\",\"rowNumber\":0,\"auditRecordTimestamp\":null,\"clubNumber\":4931,\"itemNumber\":123,\"effectiveDate\":\"2022-12-29\",\"submissionID\":null,\"retailAmount\":55.0,\"createdBy\":\"lab1 account\"}";
String key2 = "{\"retailTypeReasonCode\":{\"retailTypeReasonCodeId\":{\"retailType\":\"BP\",\"retailReasonCode\":\"CC\"}},\"expirationDate\":null,\"customerRetailAmount\":0.0,\"auditMessage\":null,\"createdTimestamp\":null,\"clientID\":\"COST IQ\",\"rowNumber\":0,\"auditRecordTimestamp\":null,\"categoryId\":87,\"subCategoryId\":1,\"clubNumber\":4931,\"itemNumber\":123,\"effectiveDate\":\"2022-12-29\",\"submissionID\":null,\"retailAmount\":10.0,\"createdBy\":\"lab1 account\"}";
return key2;
}
#Test
void test() throws Exception {
// Set up the mock endpoints
mock.expectedBodiesReceived(costIQPayloadString());
//p.interceptSendToEndpoint( Endpoints.SEDA_PROCESS_ENDPOINT).to(mock.getEndpointUri());
Mockito.when(rulesEngineClientMock.validateRules((costIQObject()))).thenReturn(costIQObject()); //.thenR
Map<String, Object> headers = new HashMap<>();
headers.put("appName", "costIQ");
// Send the test message to the SEDA_SEND_ENDPOINT
template.sendBodyAndHeaders(Endpoints.SEDA_SEND_ENDPOINT, costIQObject(), headers);
mock.assertIsSatisfied();
}
}
I have looked at advice with but that involves adding in the cameltestsupport and would need to re-write this code. Is there a way to do this with current implementations?

JUnit mockMVC testing spring controller classes that use hibernate. Table not mapped exceptions thrown

I'm trying to create JUnit tests for spring framework controller classes.
The class im trying to test uses hibernate/HQL to pull data from a MySQL database.
What I'm trying to test is given different parameters for the HQL, it should return specific data from the database, in this case flights.
While it does start, the test throws an exception once it tries to execute the query with
org.hibernate.hql.internal.ast.QuerySyntaxException: <tablename> is not mapped
Here is the JUnit class:
import org.junit.Before;
import org.junit.Test;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
public class SearchTest {
private MockMvc mockMvc;
private AjaxSearchController ajaxS;
#Before
public void setup() throws Exception {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
ajaxS = new AjaxSearchController();
this.mockMvc = standaloneSetup(ajaxS).setViewResolvers(viewResolver).build();
}
#Test
public void testSearch() {
String recommendation = " ";
String departure = "Perth, Australia";
String arrival = "Melbourne, Australia";
String departureDate = "2018-09-27";
try {
mockMvc.perform(post("/ajax")
.param("recommendation", recommendation)
.param("departure", departure)
.param("arrival", arrival)
.param("departureDate", departureDate));
} catch (Exception e) {
e.printStackTrace();
}
}
}
The tests are being run out of the projectname.test directory.
The controller class works fine outside of JUnit, when the webapp is run normally.
How can I get hibernate to see the entity classes it needs for these tests.
Edit:
Trying to get the web application context working.
the config.xml file is located in test/resources.
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
#RunWith(SpringRunner.class)
#WebAppConfiguration
#ContextConfiguration("classpath: config.xml")
public class SearchTest {
private MockMvc mockMvc;
#Autowired
private WebApplicationContext webApplicationContext;
#Before
public void setup() throws Exception {
this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
#Test
public void testSearch() {
String recommendation = " ";
String departure = "Perth, Australia";
String arrival = "Melbourne, Australia";
String departureDate = "2018-09-27";
try {
mockMvc.perform(post("/ajax")
.param("recommendation", recommendation)
.param("departure", departure)
.param("arrival", arrival)
.param("departureDate", departureDate));
} catch (Exception e) {
e.printStackTrace();
}
}
}
Gives the following error:
java.io.FileNotFoundException: class path resource [ config.xml] cannot be opened because it does not exist

#Value returning null in unit test

I have a spring boot app with an Endpoint Test Configuration class and a unit test to test my http client. I am trying to get my server address and port from my application.properties which is located in my src/test.(All the classes are in my src/test.)
Here is my config class code :
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import javax.xml.bind.JAXBException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.ResourceUtils;
import com.nulogix.billing.service.PredictionEngineService;
import com.nulogix.billing.ws.endpoint.AnalyzeEndPoint;
import com.nulogix.billing.ws.endpoint.GetVersionEndPoint;
#Configuration
public class EndPointTestConfiguration {
#Value("${billing.engine.address}")
private String mockAddress;
#Value("${billing.engine.port}")
private String mockPort;
#Bean
public String getAddress() {
String serverAddress = "http://" + mockAddress + ":" + mockPort;
return serverAddress;
}
#Bean
public GetVersionEndPoint getVersionEndPoint() {
return new GetVersionEndPoint();
}
I annotated the values from my .properties with #value and then created a method that I instantiated with a bean to to return my server address string.
I then use that string value here in my HttpClientTest class:
import static org.junit.Assert.*;
import java.io.IOException;
import java.util.Map;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.fluent.Request;
import org.apache.http.entity.ContentType;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ConfigurableApplicationContext;
import com.google.gson.Gson;
import com.nulogix.billing.configuration.EndPointTestConfiguration;
import com.nulogix.billing.mockserver.MockServerApp;
#SpringBootTest(classes = EndPointTestConfiguration.class)
public class HttpClientTest {
#Autowired
EndPointTestConfiguration endpoint;
public static final String request_bad = "ncs|56-2629193|1972-03-28|20190218|77067|6208|3209440|self|";
public static final String request_good = "ncs|56-2629193|1972-03-28|20190218|77067|6208|3209440|self|-123|-123|-123|0.0|0.0|0.0|0.0|0.0|0.0|0.0";
//gets application context
static ConfigurableApplicationContext context;
//call mock server before class
#BeforeClass
static public void setup(){
SpringApplication springApplication = new SpringApplicationBuilder()
.sources(MockServerApp.class)
.build();
context = springApplication.run();
}
//shutdown mock server after class
#AfterClass
static public void tearDown(){
SpringApplication.exit(context);
}
#Test
public void test_bad() throws ClientProtocolException, IOException {
// missing parameter
String result = Request.Post(endpoint.getAddress())
.connectTimeout(2000)
.socketTimeout(2000)
.bodyString(request_bad, ContentType.TEXT_PLAIN)
.execute().returnContent().asString();
Map<?, ?> resultJsonObj = new Gson().fromJson(result, Map.class);
// ensure the key exists
assertEquals(resultJsonObj.containsKey("status"), true);
assertEquals(resultJsonObj.containsKey("errorMessage"), true);
// validate values
Boolean status = (Boolean) resultJsonObj.get("status");
assertEquals(status, false);
String errorMessage = (String) resultJsonObj.get("errorMessage");
assertEquals(errorMessage.contains("Payload has incorrect amount of parts"), true);
}
#Test
public void test_good() throws ClientProtocolException, IOException {
String result = Request.Post(endpoint.getAddress())
.connectTimeout(2000)
.socketTimeout(2000)
.bodyString(request_good, ContentType.TEXT_PLAIN)
.execute().returnContent().asString();
Map<?, ?> resultJsonObj = new Gson().fromJson(result, Map.class);
// ensure the key exists
assertEquals(resultJsonObj.containsKey("status"), true);
assertEquals(resultJsonObj.containsKey("errorMessage"), false);
assertEquals(resultJsonObj.containsKey("HasCopay"), true);
assertEquals(resultJsonObj.containsKey("CopayAmount"), true);
assertEquals(resultJsonObj.containsKey("HasCoinsurance"), true);
assertEquals(resultJsonObj.containsKey("CoinsuranceAmount"), true);
assertEquals(resultJsonObj.containsKey("version"), true);
// validate values
Boolean status = (Boolean) resultJsonObj.get("status");
assertEquals(status, true);
String version = (String) resultJsonObj.get("version");
assertEquals(version, "0.97");
}
}
I use it in the request.post, I didn't want to hardcode in my IP address and port number.
When I run the test it says
[ERROR] HttpClientTest.test_bad:63 NullPointer
[ERROR] HttpClientTest.test_good:86 NullPointer
But I am not sure why it is null? I am pretty sure I have everything instantiated and the string is clearly populated..
My package structure for my config is com.billing.mockserver and my package structure for my unit test is com.billing.ws.endpoint.
Here is my application.properties
server.port=9119
server.ssl.enabled=false
logging.config=classpath:logback-spring.xml
logging.file=messages
logging.file.max-size=50MB
logging.level.com.nulogix=DEBUG
billing.engine.address=127.0.0.1
billing.engine.port=9119
billing.engine.api.version=0.97
billing.engine.core.name=Patient_Responsibility
You are missing springboot basic understanding. #Configuration class is to initialize other spring beans and other things and are the first classes which get initialized. You should not #Autowire #configuration class.
In your Configuration class you can either create Spring bean for username and password and autowire that in your test class or directly use #Value in your Test class.
Example: in your configuration class you are creating bean of GetVersionEndPoint and you can autowire that in your Test class.
Update 2:
For test classes, you need to add application.properties file in src\test\resource

Proper way to mock MIMEMessage?

I want to actually verify the fields set on the message, like the body, subject, from, etc… I’ve tried doing an argument captor as well which didn’t work and when I debug the code, the message is always showing null fields when it gets the javaMailSender.send(message) line.
Are there best practices in mocking MIMEMessage?
//EmailService.java
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
#Slf4j
public class EmailService {
private JavaMailSender javaMailSender;
#Autowired
public EmailService(JavaMailSender javaMailSender) {
this.javaMailSender = javaMailSender;
}
public void sendEmail() {
MimeMessage message = javaMailSender.createMimeMessage();
String body = "<html>\n" +
"<p> This the body </p>\n" +
"<br>\n";
try {
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(message, true);
mimeMessageHelper.setSubject("subject");
mimeMessageHelper.setTo("stack#overflow.com");
mimeMessageHelper.setFrom("overflow#stack.com");
mimeMessageHelper.setText(body, true);
javaMailSender.send(message);
} catch (MessagingException e) {
log.error("error");
}`enter code here`
}
}
Below is the test
//EmailServiceTest.java
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.springframework.mail.javamail.JavaMailSender;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.IOException;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;
import static org.mockito.MockitoAnnotations.initMocks;
public class EmailServiceTest {
private EmailService emailService;
#Mock
private JavaMailSender javaMailSender;
#Mock
private MimeMessage message;
#Before
public void setUp() throws IOException {
initMocks(this);
emailService = new EmailService(javaMailSender);
}
#Test
public void sendEmail_sendsEmailWithCorrectContent() throws MessagingException {
ArgumentCaptor<MimeMessage> mimeMessageArgumentCaptor = ArgumentCaptor.forClass(MimeMessage.class);
when(javaMailSender.createMimeMessage()).thenReturn(message);
doNothing().when(javaMailSender).send(message);
emailService.sendEmail();
verify(javaMailSender, times(1)).send((mimeMessageArgumentCaptor.capture()));
assertEquals("subject", mimeMessageArgumentCaptor.getValue().getSubject());
}
}
It's generally easier to do this kind of testing using an integration test. Emails are often built using a template library such as freemarker, so an integration test is valuable in being able to verify that your template is correct as well.
You could do unit testing by using PowerMock to create a mock MimeMessageHelper, but PowerMock can sometimes be slow at keeping up with changes to other testing libraries, and such tests often end up brittle and of little value. For example, you could verify that setSubject() was called on mimeMessageHelper, but does that produce the outcome that you really want to test (that the subject is set on message)?

Tested class is calling actual object, instead of mocked object

I'm trying to mock an external library, however the actual object created in APKDecompiler is being used, instead of the mock object.
Test code
import com.googlecode.dex2jar.v3.Dex2jar;
import jd.core.Decompiler;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import APKDecompiler;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.junit.Assert.assertEquals;
import static org.powermock.api.easymock.PowerMock.*;
import java.io.File;
import java.io.IOException;
#RunWith(PowerMockRunner.class)
#PrepareForTest({Dex2jar.class})
public class TestAPKDecompiler {
//As this only uses external libraries, I will only test that they are called correctly by mocking them.
#Test
public void testAPKDecompiler() {
try {
File testFile = new File("ApkExtractor/src/test/resources/testApp.jar");
String expectedDirectory = testFile.getAbsolutePath().substring(0, testFile.getAbsolutePath().length() - 4);
mockStatic(Dex2jar.class);
Dex2jar mockApkToProcess = createMock(Dex2jar.class);
Decompiler mockDecompiler = createNiceMockAndExpectNew(Decompiler.class);
expect(Dex2jar.from(testFile)).andStubReturn(mockApkToProcess);
mockApkToProcess.to(new File(expectedDirectory + ".jar"));
expectLastCall();
PowerMock.expectNew(Decompiler.class).andReturn(mockDecompiler).anyTimes();
expect(mockDecompiler.decompileToDir(expectedDirectory + ".jar", expectedDirectory)).andReturn(0);
replay(mockApkToProcess);
PowerMock.replay(mockDecompiler);
replayAll();
String actualDirectory = APKDecompiler.decompileAPKToDirectory(testFile);
verify(mockApkToProcess);
verify(mockDecompiler);
verifyAll();
assertEquals(expectedDirectory, actualDirectory);
testFile.delete();
}
catch(Exception e){
e.printStackTrace();
}
}
}
Class code
import com.googlecode.dex2jar.v3.Dex2jar;
import jd.core.Decompiler;
import jd.core.DecompilerException;
import java.io.File;
import java.io.IOException;
public class APKDecompiler {
public static String decompileAPKToDirectory(File filename) throws IOException, DecompilerException {
String filenameWithoutFileExtension = filename.getAbsolutePath().substring(0, filename.getAbsolutePath().length() - 4);
Dex2jar apkToProcess = Dex2jar.from(filename);
File jar = new File(filenameWithoutFileExtension + ".jar");
apkToProcess.to(jar);
Decompiler decompiler = new Decompiler();
decompiler.decompileToDir(filenameWithoutFileExtension + ".jar", filenameWithoutFileExtension);
return filenameWithoutFileExtension;
}
I've tried this and I haven't had any luck. EasyMock: Mocked object is calling actual method
I get a FileNotFoundException when decompiler.decompileToDir is called, which shouldn't happen as I should be mocking the class.
Any help would be greatly appreciated.
The answer was I didn't include the class i was testing in the #PrepareForTest annotation.
#PrepareForTest({APKDecompiler.class, Dex2jar.class, Decompiler.class})

Categories

Resources