I tried multiple way to execute the store procedure in my Junit test case to test against the out values but unfortunately nothing is working.
My Test case:
public class DataTest {
#Mock
private static DataSource ds;
#InjectMocks
private DataDaoImpl dataDao = new DataDaoImpl();
#Mock
private static JdbcTemplate jdbcTemplate;
#Mock
private static SimpleJdbcCall viewProc;
#Before
public void setUp() throws IOException, InterruptedException {
MockitoAnnotations.initMocks(this);
MockMvcBuilders.standaloneSetup(dataDao).build();
}
#BeforeClass
public static void init() throws Exception {
viewProc = new SimpleJdbcCall(ds).withSchemaName("schema")
.withProcedureName("viewProc").withoutProcedureColumnMetaDataAccess()
.declareParameters(new SqlParameter("param1", Types.VARCHAR))
.declareParameters(new SqlParameter("param2", Types.VARCHAR))
.returningResultSet("dataModules", Mockito.anyObject());
jdbcTemplate = new JdbcTemplate(ds);
}
#Test
public void findDataModules() throws Exception {
String param1 = "abc";
List<DataObj> md = new ArrayList<DataObj>();
int size = 3;
SqlParameterSource in = new MapSqlParameterSource().addValue("param1", "abc").addValue("param2",
"123");
Map map = viewProc.execute(in);
md = (List<DataObj>) map.get("data");
assertTrue("Expected Data ", md.size() >= size);
}
}
My Main class:
#Repository
public class DataDaoImpl implements DataDao {
protected Logger logger = LoggerFactory.getLogger(getClass());
#Resource(name = "db")
private DataSource db;
private SimpleJdbcCall viewProc;
private JdbcTemplate jdbcTemplate;
/**
* Initialization of Stored Procs and JDBC Template
*
* #throws Exception
*/
#PostConstruct
public void init() throws Exception {
viewProc = new SimpleJdbcCall(db).withSchemaName("schema")
.withProcedureName("viewProc").withoutProcedureColumnMetaDataAccess()
.declareParameters(new SqlParameter("param1", Types.VARCHAR))
.declareParameters(new SqlParameter("param2", Types.VARCHAR))
.returningResultSet("data", new ViewDataRowMapper());
jdbcTemplate = new JdbcTemplate(db);
}
#Override
public List<Data> findUniqueDataModules(String p1, String p2) throws Exception {
List<DataObj> dataModules = new ArrayList<DataObj>();
try {
SqlParameterSource in = new MapSqlParameterSource().addValue("param1", p1).addValue("param2",
p2);
Map map = viewUniqueDataModulesByLicense.execute(in);
dataModules = (List<DataObj>) map.get("data");
} catch (Exception e) {
//Hnadel Exception
}
return dataModules;
}
}
Above code gives exception says datasource is required.
I tried Mockito, powerMockito but it returning empty map. There is no exceptions with mock.
I am OK with any solution which can pass my test case.
Modified naming.
As much as I hate using reflection in testing, I believe it can help you in your case. Here, after initializing, I set the field viewProc to a mock object which you can use in the test. #PostConstruct is a Spring related annotation, so it will not be called while initializing it.
class DataDaoImplTest {
private DataDaoImpl dataDao;
#Mock
private DataSource dataSource;
#Mock
private SimpleJdbcCall jdbcCall;
#BeforeEach
void setUp() {
MockitoAnnotations.initMocks(this);
this.dataDao = new DataDaoImpl(dataSource);
ReflectionTestUtils.setField(this.dataDao, "viewProc", jdbcCall);
}
#Test
void findUniqueDataModules() throws Exception {
// given:
Map<String, Object> map = new HashMap<>();
map.put("data", Arrays.asList(new DataDaoImpl.DataObj(), new DataDaoImpl.DataObj()));
// mocks:
when(jdbcCall.execute(any(SqlParameterSource.class))).thenReturn(map);
// when:
List<DataDaoImpl.DataObj> uniqueDataModules = this.dataDao.findUniqueDataModules("a", "b");
// then:
assertEquals(2, uniqueDataModules.size());
}
}
Another solution would be to test the method against a test database, like H2. But it won't be a unit test.
Related
I am facing issues in mocking static method.
Below is my code where I am calling a static method
public class GetAllBatches {
public HttpResponseMessage run(
#HttpTrigger(route = "v1/batches",
name = "request",
methods = {HttpMethod.GET},
authLevel = AuthorizationLevel.ANONYMOUS)
HttpRequestMessage<String> request,
final ExecutionContext context){
context.getLogger().info("List batches Called");
String apiResponse ;
String connector = request.getQueryParameters().getOrDefault("connector", "");
try{
BatchesController batchesController = BatchesController.getInstance();
apiResponse = new Gson().toJson(batchesController.getBatches(connector));
}
}
}
BatchesController Class :
public class BatchesController {
Logger log = Logger.getLogger(BatchesController.class.getName());
public static BatchesController getInstance() {
if (batchesController == null) {
batchesController = new BatchesController(BatchDaoFactory.getDao());
}
return batchesController;
}
private static BatchesController batchesController = new BatchesController();
private final BatchDao batchDao;
public BatchesController(BatchDao BatchDao) {
this.batchDao = BatchDao;
}
// Do something
}
And below is the test that I have :
#RunWith(MockitoJUnitRunner.class)
public class GetAllBatchesTest {
#Mock
ExecutionContext context;
#Mock
HttpRequestMessage<String> request;
#Mock
BatchesController batchesController;
#Mock
BatchDao BatchDao;
#InjectMocks
GetAllBatches getAllBatchesMock = new GetAllBatches();
#Before
public void setUp() {
Map<String, String> map = new HashMap<>();
map.put("connector", "");
doReturn(Logger.getGlobal()).when(context).getLogger();
doReturn(map).when(request).getQueryParameters();
try (MockedStatic<BatchesController> utilities = Mockito.mockStatic(BatchesController.class)) {
utilities.when(BatchesController::getInstance).thenReturn(batchesController);
}
doAnswer((Answer<HttpResponseMessage.Builder>) invocationOnMock -> {
HttpStatus status = (HttpStatus) invocationOnMock.getArguments()[0];
return new HttpResponseMessageMock.HttpResponseMessageBuilderMock().status(status);
}).when(request).createResponseBuilder(any(HttpStatus.class));
}
#Test
public void testHttpTriggerJava() {
final HttpResponseMessage ret = getAllBatchesMock.run(request, context);
Assertions.assertEquals(ret.getStatus(), HttpStatus.OK);
}
When I run my test, it throws an error message :
java.lang.ExceptionInInitializerError
BatchesController.getInstance() is not actually returning the mock value.
I am not sure what is going wrong here ?
UPDATE :
I found out that the problem is because I am using Mockito-inline Mockito-inline fails to initiate mock on class but initiates mock only on interfaces
You are using a try-with-resources block to setup a static mock:
try (MockedStatic<BatchesController> utilities = Mockito.mockStatic(BatchesController.class)) {
utilities.when(BatchesController::getInstance).thenReturn(batchesController);
}
Remember that the static mock is only active in scope of the block - after you exit the block the resource is closed.
Thus, you need to:
move the static mock initialization from setup method to the test method
run code under test within the try-with-resources block
I have the following code to send data to Kafka:
#Service
public class KafkaSender{
#Autowired
private KafkaTemplate<String, Employee> kafkaTemplate;
public void sendMessage(Employee employee) {
ObjectMapper objectMapper = new ObjectMapper();
ListenableFuture<SendResult<String, Employee>> listenableFuture = kafkaTemplate.send(topic,employee);
listenableFuture.addCallback(new ListenableFutureCallback<SendResult<String, Employee>>() {
#Override
public void onSuccess(SendResult<String, Employee> result) {
// method to save in DB
saveInDatabaseMethod(result.getProducerRecord());
}
#Override
public void onFailure(Throwable ex) {
// class cast exception occur here
ProducerRecord<String, Employee> producerRecord = ((KafkaProducerException) ex).getFailedProducerRecord();
saveInDatabaseMethod(producerRecord);
}
}
}
}
I am able to test the OnSucess callback scenario, but i am not able to test the OnFailure one.
#Test
void test() throws InterruptedException, ExecutionException {
Throwable ex = mock(Throwable.class);
Employee employee = new Employee();
when(kafkaTemplate.send(null,employee )).thenReturn(responseFuture);
when(sendResult.getProducerRecord()).thenReturn(producerRecord);
when(producerRecord.value()).thenReturn(employee);
doAnswer(invocationOnMock -> {
ListenableFutureCallback<SendResult<String, Employee>> listenableFutureCallback = invocationOnMock.getArgument(0);
listenableFutureCallback.onFailure(ex);
return null;
}).when(responseFuture).addCallback(any(ListenableFutureCallback.class));
kafkaSender.sendMessage(employee);
}
The above test throws:
java.lang.ClassCastException:
org.mockito.codegen.Throwable$MockitoMock$2137573915 cannot be cast to
org.springframework.kafka.core.KafkaProducerException
ProducerRecord<String, Employee> producerRecord = ((KafkaProducerException) ex).getFailedProducerRecord();
Your mock is not calling the callback with a KPE, its calling it with this
Throwable ex = mock(Throwable.class);
You need to wrap it in a KPE.
I have controller method and for it I am making Junit but getting Null pointer error when it calling a service method. I used power mock but still getting Null pointer.
method:
#RequestMapping(method = RequestMethod.GET, value = "/DSR.do")
public ModelAndView displayDataSourceReportPage(HttpServletRequest request,Model model) {
log.debug(" Inside displayDataSourceReportPage method ");
Map<String, Object> map = new HashMap<String, Object>();
try {
request.setAttribute(MENU_SELECTED, LABEL_MENU_SOURCEDATA);
request.setAttribute(SUB_MENU_SELECTED, LABEL_SUBMENU_DSR);
#SuppressWarnings("rawtypes")
List dataSource = dataSourceReportService.listDataSourceReportByCurrentRunInd("C");
map.put("dataSource", dataSource);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return new ModelAndView("DataSourceReport", "model", map);
}
test Method:
#InjectMocks
private DataSourceReportController dataSourceReportController;
#Mock
private DataSourceReportService dataSourceReportServiceImpl;
#InjectMocks
private DataSourceReportDAO dataSourceReportDAO = new DataSourceReportDAOImpl();
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testdisplayDataSourceReportPage() throws Exception {
PowerMockito.mockStatic(DataSourceReport.class);
PowerMockito.mockStatic(HttpServletRequest.class);
PowerMockito.mockStatic(Model.class);
PowerMockito.mockStatic(DataSourceReportService.class);
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
Model model = Mockito.mock(Model.class);
dataSourceReportServiceImpl = PowerMockito.mock(DataSourceReportService.class);
DataSourceReport dataSourceReport = PowerMockito.mock(DataSourceReport.class);
dataSourceReport.setCurrentRunInd("abc");
dataSourceReport.setActualFileName("Somthing");
dataSourceReport.setFileCountId(3);
dataSourceReport.setFileId(4);
dataSourceReport.setRecCount(3);
List<DataSourceReport> list = new ArrayList<DataSourceReport>();
list.add(dataSourceReport);
String currentRunInd = "currentRunInd";
Object obj =getClass();
PowerMockito.when(dataSourceReportDAO.listDataSourceReportByCurrentRunInd(currentRunInd)).thenReturn(list);
DataSourceReportController ctrl = new DataSourceReportController();
ctrl.displayDataSourceReportPage(request, model);
}
getting Null at "dataSourceReportService.listDataSourceReportByCurrentRunInd("C");"
You need to have this in the test class
PowerMockito.when(dataSourceReportService.listDataSourceReportByCurrentRunInd("C")).thenReturn(list);
before calling
ctrl.displayDataSourceReportPage(request, model);
Thanks # Arthur Zagretdinov
I tried the below code and it worked.
private MockMvc mockMvc;
#Mock
private HttpServletRequest req;
#Mock
private DataSourceReportService dataSourceReportServiceImpl;
#InjectMocks
private DataSourceReportController controller;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
}
#Before
public void initMocks(){
MockitoAnnotations.initMocks(this);
}
#Test
public void testdisplayDataSourceReportPage() throws Exception {
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
Model model = Mockito.mock(Model.class);
DataSourceReport dataSourceReport =Mockito.mock(DataSourceReport.class);;
dataSourceReport.setCurrentRunInd("abc");
dataSourceReport.setActualFileName("Somthing");
dataSourceReport.setFileCountId(3);
dataSourceReport.setFileId(4);
dataSourceReport.setRecCount(3);
List<DataSourceReport> list = new ArrayList<DataSourceReport>();
list.add(dataSourceReport);
ModelAndView modelView = controller.displayDataSourceReportPage(request, model);
modelView.addObject(dataSourceReport);
}
I have a Java class that extends QuartzJobBean and has been scheduled at a specific time through out the day.
public class ServiceJob extends QuartzJobBean {
#Override
protected void executeInternal(JobExecutionContext context) {
}
Can someone please help me understand how to create a Junit test case for this. How do I invoke the executeInternal() method in the test case.
Thanks for any help on this.
I create a solution for my working project, i agree to adarshdatt to solve it via importing config file that defined the bean. You can find a good tutorial about it at this blog post,
For future use I want to show how i solve it with Mocking, just use Mockito #Mock annotation with this way :
SessionConfirmationJob.java
public class SessionConfirmationJob extends QuartzJobBean {
#Autowired
private SessionService sessionService;
#Autowired
private TransactionService transactionService;
#Autowired
private SystemLogger systemLogger;
public static final String TOKEN = "token";
private SpringInjectQuartzJobBean springInjectQuartzJobBean;
public SessionService getSessionService() {
return sessionService;
}
public void setSessionService(SessionService sessionService) {
this.sessionService = sessionService;
}
public TransactionService getTransactionService() {
return transactionService;
}
public void setTransactionService(TransactionService transactionService) {
this.transactionService = transactionService;
}
public void setSpringInjectQuartzJobBean(SpringInjectQuartzJobBean springInjectQuartzJobBean) {
this.springInjectQuartzJobBean = springInjectQuartzJobBean;
}
public SystemLogger getSystemLogger() {
return systemLogger;
}
public void setSystemLogger(SystemLogger systemLogger) {
this.systemLogger = systemLogger;
}
#Override
protected void executeInternal(JobExecutionContext paramJobExecutionContext) throws JobExecutionException {
springInjectQuartzJobBean = new SpringInjectQuartzJobBean();
springInjectQuartzJobBean.injectQuartzJobToSpringApplicationContext(this);
String token = paramJobExecutionContext.getMergedJobDataMap().getString(TOKEN);
Session session = sessionService.getByToken(token);
if (session != null) {
if (session.getPaymentConfirmation() == null || session.getPaymentConfirmation() != true) {
Transaction transactionToBeRolledBack = transactionService.getRollBackTransactionOfPayment(session);
if (transactionToBeRolledBack != null) {
try {
transactionService.rollBackTransaction(transactionToBeRolledBack);
} catch (IOException e) {
systemLogger.logException("Exception while rolling back transaction", e);
}
session = sessionService.getByToken(token);
session.setStatus(SessionStatus.FI);
session.setPaymentConfirmation(false);
sessionService.saveOrUpdate(session);
}
}
}
}
}
This is the method i should write test and this is the testing class.
SessionConfirmationJobTest.java
#RunWith(MockitoJUnitRunner.class)
public class SessionConfirmationJobTest {
#Mock
private SessionService sessionService;
#Mock
private TransactionService transactionService;
#Mock
private JobExecutionContext ctx;
#Mock
private SpringInjectQuartzJobBean springInjectQuartzJobBean;
private JobDataMap mergedJobDataMap = new JobDataMap();
#Mock
private Scheduler scheduler;
private SessionConfirmationJob sessionConfirmationJob;
private String token = "payment token";
#Before
public void setUp() throws SchedulerException {
mergedJobDataMap.put(SessionConfirmationJob.TOKEN, token);
when(ctx.getMergedJobDataMap()).thenReturn(mergedJobDataMap);
when(ctx.getScheduler()).thenReturn(scheduler);
when(scheduler.getContext()).thenReturn(null);
sessionConfirmationJob = new SessionConfirmationJob();
sessionConfirmationJob.setSessionService(sessionService);
sessionConfirmationJob.setTransactionService(transactionService);
sessionConfirmationJob.setSpringInjectQuartzJobBean(springInjectQuartzJobBean);
}
/**
* Test payment confirmation when we have false payment confirmation
*
* #throws JobExecutionException
*/
#Test
public void testPaymentRollBackForFalseConfirmation() throws IOException, JobExecutionException {
Session session = new Session();
session.setStatus(SessionStatus.AC);
session.setPaymentConfirmation(false);
Transaction transaction = new Transaction();
transaction.setSession(session);
transaction.setType(TransactionType.SALE);
transaction.setStatus(TransactionStatus.AP);
when(sessionService.getByToken(token)).thenReturn(session);
when(transactionService.getRollBackTransactionOfPayment(session)).thenReturn(transaction);
when(transactionService.rollBackTransaction(transaction)).thenReturn(true);
sessionConfirmationJob.execute(ctx);
Assert.assertEquals(SessionStatus.FI, session.getStatus());
Assert.assertFalse(session.getPaymentConfirmation());
verify(sessionService).saveOrUpdate(session);
}
}
Before mock the Schedular object i get NullPointerException at pvs.addPropertyValues(context.getScheduler().getContext()); after i mock schedular it is solved and my test is passed. Below is the
org.springframework.scheduling.quartz.QuartzJobBean#execute(JobExecutionContext context) method. Actually executeInternal is protected so we must call execute method first then execute method is call executeInternal which is override at your implemented Job class(my demo it is SessionConfirmationJob).
QuartzJobBean.java
public abstract class QuartzJobBean implements Job {
/**
* This implementation applies the passed-in job data map as bean property
* values, and delegates to {#code executeInternal} afterwards.
* #see #executeInternal
*/
#Override
public final void execute(JobExecutionContext context) throws JobExecutionException {
try {
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
MutablePropertyValues pvs = new MutablePropertyValues();
pvs.addPropertyValues(context.getScheduler().getContext());
pvs.addPropertyValues(context.getMergedJobDataMap());
bw.setPropertyValues(pvs, true);
}
catch (SchedulerException ex) {
throw new JobExecutionException(ex);
}
executeInternal(context);
}
/**
* Execute the actual job. The job data map will already have been
* applied as bean property values by execute. The contract is
* exactly the same as for the standard Quartz execute method.
* #see #execute
*/
protected abstract void executeInternal(JobExecutionContext context) throws JobExecutionException;
}
If you have question don't hesitate to ask me via comments.
I'm very new to Junit.
I'm writing junit for a interceptor.. It contains SessionMap in that.. while calling the interceptor from the test class I'm getting Null pointer exception at Session Map.
Below is my interceptor..
public String intercept(ActionInvocation actionInv) throws Exception {
ActionContext context = actionInv.getInvocationContext();
final HttpServletRequest request = (HttpServletRequest) context.get(ServletActionContext.HTTP_REQUEST);
String callerAppName = request.getParameter(CustomerPortalConstants.CALLER);
if(callerAppName == null){
//caller name is passed in header in case of OnePortal service request
callerAppName = request.getHeader(CustomerPortalConstants.CALLER);
}
SessionMap<String,Object> sessionMap = ((SessionMap<String,Object>)ActionContext.getContext().getSession());
#SuppressWarnings("unchecked")
Map<String,AccountBean> accountsMap = (Map<String,AccountBean>)sessionMap.get(CustomerPortalConstants.ACCOUNTSMAP);;
if(accountsMap == null) {
accountsMap = new HashMap<String, AccountBean>();
sessionMap.put(CustomerPortalConstants.ACCOUNTSMAP, accountsMap);
}
Im getting error at this location
((SessionMap)ActionContext.getContext().getSession());
This is my Test class..
public class MultiAccountInterceptorTest extends StrutsTestCase implements SessionAware {
/**
*
*/
private static final long serialVersionUID = 1L;
private Map<String,AccountBean> accountsMap=new HashMap<String, AccountBean>();
Map<String, Object> sessionMap;
private String callerAppName="LMP";
private final HttpServletRequest mockHttpReq = createMock(HttpServletRequest.class);
MultiAccountInterceptor interceptor = new MultiAccountInterceptor();
#SuppressWarnings("unchecked")
#Before
public void setUp() throws Exception {
sessionMap = new HashMap<String, Object>();
}
#SuppressWarnings("unchecked")
#Test
public void testIntercept() throws Exception
{
MultiAccountInterceptor mockInterceptor = PowerMock.createNicePartialMockForAllMethodsExcept(MultiAccountInterceptor.class, "intercept");
final ActionInvocation mockInvocation = createMock(ActionInvocation.class);
final ActionContext mockContext = createMock(ActionContext.class);
expect(mockInvocation.getInvocationContext()).andReturn(mockContext);
System.out.println(mockContext);
expect( (HttpServletRequest)mockContext.get(ServletActionContext.HTTP_REQUEST)).andReturn(mockHttpReq);
System.out.println(mockHttpReq);
expect(mockHttpReq.getParameter(CustomerPortalConstants.CALLER)).andReturn(callerAppName);
System.out.println("Caller app name is"+ callerAppName);
System.out.println(sessionMap);
sessionMap.put(CustomerPortalConstants.ACCOUNTSMAP, accountsMap);
System.out.println(sessionMap);
replayAll();
mockInterceptor.intercept(mockInvocation);
}
#Override
public void setSession(Map<String, Object> sessionMap) {
this.sessionMap=sessionMap;
}
}
Can anyone provide me a solution for this problem..
Thanks in advance..