Not able to mock connection.prepareCall method - spring

I am not able to mock connection.prepareCall("{call myStoreProcedure()}"); call in spring boot project.
Every time i am getting "org.h2.jdbc.JdbcSQLSyntaxErrorException: Column "myStoreProcedure" not found; SQL statement:", because i am using h2 database and there we dont have that procedure. But when i mock it should not call the database it should return the mock value only..but its not happening.
Note : I am getting above exception but my test cases are passing.
Below is the my code snippet :
package com.khan;
import static org.mockito.Mockito.mock;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import javax.sql.DataSource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.modules.junit4.PowerMockRunnerDelegate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
#RunWith(PowerMockRunner.class)
#PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)
#PrepareForTest({ DataSource.class, Connection.class, CallableStatement.class })
#SpringBootTest
#PowerMockIgnore({ "javax.management.*", "javax.net.ssl.*", "javax.security.auth.*" })
#TestPropertySource({ "classpath:application.properties" })
public class MainClassTest {
#Autowired
MainClass mainClass;
#Autowired
private DataSource dataSource;
#Test
public void testMethod() throws Exception {
ResultSet resultSet = mock(ResultSet.class);
CallableStatement callableStatement = mock(CallableStatement.class);
Mockito.when(dataSource.getConnection()).thenReturn(connection);
Mockito.when(connection.prepareCall("{ call myprocedure()}")).thenReturn(callableStatement);
Mockito.when(callableStatement.executeQuery()).thenReturn(resultSet);
//Tried below one as well but no luck
//PowerMockito.stub(PowerMockito.method(Connection.class, "prepareCall", Mockito.any())).toReturn(callableStatement);
mainClass.callProcedure("Procedure Name");
}
}
Below is my MainClass :
public class MainClass{
#Autowired
private DataSource dataSource;
public void callProcedure(String storedProcName) throws SQLException {
Connection connection = dataSource.getConnection();
try (CallableStatement cs = connection.prepareCall("{call " + storedProcName + "}");) { // I am getting exception here but test cases are passing
cs.executeQuery();
} catch (SQLException e) {
log.error("Exception occured while execution of stored procedure having storedProcName: {} with reason: {} "
+ e.getMessage(), storedProcName, e);
throw e;
}
}
}

I see lot of issues in your testCase.
No need to load Spring Context for testing this class. Mock should be enough.
In your callProcedure you are passing "Procedure Name" but in mock you expect "{ call myprocedure()}" so that mock will never get triggered.
Your test case passes as you not verifying anything.
Try something like below.
#RunWith(PowerMockRunner.class)
public class MainClassTest {
#InjectMocks
MainClass mainClass;
#Mock
private DataSource dataSource;
#Test
public void testMethod() throws Exception {
//Given
ResultSet resultSet = mock(ResultSet.class);
CallableStatement callableStatement = mock(CallableStatement.class);
Mockito.when(dataSource.getConnection()).thenReturn(connection);
Mockito.when(connection.prepareCall(anyString())).thenReturn(callableStatement);
Mockito.when(callableStatement.executeQuery()).thenReturn(resultSet);
//When
mainClass.callProcedure("Procedure Name");
//Then
verify(dataSource, times(1)).getConnection();
}
}

Related

Property or field 'config' cannot be found on null

I am trying to Implement InitializingBean on my StudentDaoImpl.class and in the function afterPropertiesSet() trying to execute an expression using ExpressionParser, but Spring is saying that property config is not found or is null even if I have declared config in my App.propperties.
AppConfig.class(Configuration Class)
package config;
import dao.StudentDAOImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import javax.sql.DataSource;
#Configuration
#PropertySource("classpath:App.properties")
public class AppConfig {
#Bean("jdbcTemplete")
public JdbcTemplate jdbcTemplate() {
JdbcTemplate template = new JdbcTemplate();
template.setDataSource(dataSource());
return template;
}
#Bean("dataSource")
public DataSource dataSource() {
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/springjdbc");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
#Bean("StudentDaoImpl")
public StudentDAOImpl studentDaoImpl() {
StudentDAOImpl studentdao = new StudentDAOImpl(jdbcTemplate());
return studentdao;
}
#Bean("getProperties")
public static PropertySourcesPlaceholderConfigurer getProperties() {
return new PropertySourcesPlaceholderConfigurer();
}
}
StudentDaoImpl.class (I have removed methods of StudentDao Interface from the code below for you to see properly)
package dao;
import entities.Student;
import mapper.StudentMapper;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import java.util.List;
public class StudentDAOImpl implements StudentDAO, InitializingBean {
private JdbcTemplate jdbcTemplate;
#Value("${config}")
String s;
public StudentDAOImpl(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
#Override
public void afterPropertiesSet() throws Exception {
ExpressionParser expressionParser = new SpelExpressionParser();
System.out.println(s);
Expression expression = expressionParser.parseExpression("config");
String result = (String)expression.getValue();
System.out.println(result);
// if(result == true) {
// System.out.println("[Configuration]: Java Configuration");
// } else {
// System.out.println("[Configuration]: XML Configuration");
// }
}
}
App.properties
config=java
Also, I have seen that I was able to access the property from App.properties using #Value but not with ExpressionParser, Please help me solve this issue.
?
You are parsing a String, not the field; use
Expression expression = expressionParser.parseExpression(config);
to parse an expression in field config - however the value java is not a valid expression.
It is not at all clear what you are trying to do.

Hive and Impala query result not matching [timestamp]

I'm working on a code where we are removing impala connection to hive beeline. changes are working as we expected. but when we try to query some data using impala , it came up with some additional timestamp with the date.
Sample Query: select cob_date from xxx_table where cob_date='2022-03-20';
outcome of the above query in impala is : 2022-03-20 05:00:00
but usually it will return like : 2022-03-20 00:00:00
but the same query giving proper response when try from hive : 2022-03-20 00:00:00
can anyone help me to understand whats going on here.
Thanks in advance .
package com.rest;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.rest.controller.PersonController;
import com.rest.entity.Person;
import com.rest.repository.PersonRepository;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import static org.hamcrest.Matchers.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
#RunWith(MockitoJUnitRunner.class)
public class PersonControllerTest {
private MockMvc mockMvc;
ObjectMapper mapper = new ObjectMapper();
ObjectWriter writer = mapper.writer();
#Mock
private PersonRepository personRepository;
#InjectMocks
private PersonController personController;
Person person1 = new Person(1, "Arun", "Ammasai", "aj.amsi#email.com");
Person person2 = new Person(2, "Nancy", "ArulRaj", "nancymaria#email.com");
Person person3 = new Person(3, "Jack", "Daniel", "jack.daniel#email.com");
#Before
public void init() {
MockitoAnnotations.initMocks(this);
this.mockMvc = MockMvcBuilders.standaloneSetup(personController).build();
}
#Test
public void getAllSuccess() throws Exception {
List<Person> persons = Arrays.asList(person1, person2, person3);
Mockito.when(personRepository.findAll()).thenReturn(persons);
mockMvc.perform(MockMvcRequestBuilders.get("/getall")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$", hasSize(3)))
.andExpect(jsonPath("$[2].firstName", is("Jack")));
}
#Test
public void getByIdSuccess() throws Exception {
Mockito.when(personRepository.findById(person1.getId())).thenReturn(Optional.of(person1));
mockMvc.perform(MockMvcRequestBuilders.get("/findbyId/1")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$", notNullValue()))
.andExpect(jsonPath("$.firstName", is("Arun")));
}
#Test
public void createPerson_Success() throws Exception {
Person person = Person.builder().firstName("Arun").lastName("Amsi").email("test#gmail.com").build();
Mockito.when(personRepository.save(person)).thenReturn(person);
String content = writer.writeValueAsString(person);
MockHttpServletRequestBuilder request = MockMvcRequestBuilders.post("/addperson")
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.content(content);
mockMvc.perform(request)
.andExpect(status().isOk())
.andExpect(jsonPath("$", notNullValue()))
.andExpect(jsonPath("$.firstName", is("Arun")));
}
#Test
public void updatePerson_Success() throws Exception {
Person person = Person.builder().firstName("Arun").lastName("Amsi").email("test#gmail.com").build();
Mockito.when(personRepository.findById(person.getId())).thenReturn(Optional.of(person));
Mockito.when(personRepository.save(person)).thenReturn(person);
String content = writer.writeValueAsString(person);
MockHttpServletRequestBuilder request = MockMvcRequestBuilders.put("/updateperson")
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.content(content);
mockMvc.perform(request).andExpect(status().isOk())
.andExpect(jsonPath("$", notNullValue()))
.andExpect(jsonPath("$.firstName", is("Arun")));
}
#Test
public void deletePerson_Success() throws Exception {
Mockito.when(personRepository.findById(person1.getId())).thenReturn(Optional.of(person1));
mockMvc.perform(MockMvcRequestBuilders.delete("/delete/1")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
}
}

H2 & DBUnit setup

I want to initialize an H2 in memory database using DBUnit for unit tests with a schema. I based my code on https://www.baeldung.com/java-dbunit and tried to amend it to use a table with a schema. Using the H2 console, I can see that the schema has been created and that the table has been created in the schema, but the table is empty and the assertion fails.
package de.kn.info.accountplus.add.mediation.energy.importCifE1;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.dbunit.DataSourceBasedDBTestCase;
import org.dbunit.database.DatabaseConfig;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
import org.h2.jdbcx.JdbcDataSource;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
#RunWith(JUnit4.class)
public class DBUnitByBaeldungTest extends DataSourceBasedDBTestCase {
private Connection connection;
#Override
protected DataSource getDataSource() {
JdbcDataSource dataSource = new JdbcDataSource();
dataSource.setURL(
"jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;mode=Oracle;init=runscript from 'file:C:/Users/me/Projects/add/test-resources/de/kn/info/accountplus/add/mediation/energy/importCifE1/acctSys-schema.sql'");
dataSource.setUser("SA");
return dataSource;
}
#Override
protected IDataSet getDataSet() throws Exception {
IDataSet dataset = new FlatXmlDataSetBuilder().build(new FileInputStream("C:\\Users\\me\\Projects\\add\\test\\de\\kn\\info\\accountplus\\add\\resource\\myDatasetV1.xml"));
return dataset;
}
#Override
protected void setUpDatabaseConfig(DatabaseConfig config) {
config.setProperty(DatabaseConfig.FEATURE_QUALIFIED_TABLE_NAMES, true);
}
#Before
public void setUp() throws Exception {
super.setUp();
connection = getConnection().getConnection();
}
#After
public void tearDown() throws Exception {
super.tearDown();
}
#Test
public void readDB() throws SQLException {
ResultSet rs = connection.createStatement().executeQuery("select * from AP.ACCTSYS");
assertThat(rs.next(), equalTo(true));
System.out.println(rs.getString(1));
}
}
The schema file
DROP SCHEMA IF EXISTS AP;
CREATE SCHEMA AP;
create table if not exists AP.ACCTSYS
(
EINTRAG VARCHAR2(60) not null
constraint PK_ACCTSYS
primary key,
WERT VARCHAR2(512)
);
and the dataset file
<?xml version='1.0' encoding='UTF-8'?>
<dataset>
<AP.ACCTSYS EINTRAG="ONE" WERT="TWO" />
</dataset>
Can anyone see what I am missing

Mockito when().thenReturn doesn't give expected result

I am new to Junit and Mockito.
Trying to mock one of the object of the class, but it is not working.
The mock method is returning an empty list, due to which test case is getting failed.
This is the code which I have written.
Junit Test Class : Here I have mocked the object and method to return an Arraylist, but when the code is executed this mock method is returning an empty list due to which test case is getting failed.
package com.business;
import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import java.util.List;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import com.data.api.ToDoService;
public class TodoBusinessImplMockTest {
#Before
public void setUp() throws Exception {
}
#After
public void tearDown() throws Exception {
}
#Test
public void testRetrieveTodosRelatedToSpringUsingMock()
{
ToDoService todoServiceMock = mock(ToDoService.class);
List<String> todoList=Arrays.asList("Learn Spring MVC", "Learn Spring","Learn to Dance");
Mockito.when(todoServiceMock.retrieveTodos("Dummy")).thenReturn(todoList);
TodoBusinessImpl todoBusinessImpl = new TodoBusinessImpl(todoServiceMock);
List<String> todos = todoBusinessImpl.retrieveTodosRelatedToSpring("Ranga");
assertEquals(2, todos.size());
}
}
Interface : ToDoService.java
package com.data.api;
import java.util.List;
public interface ToDoService {
public List<String> retrieveTodos(String s);
}
TodoBusinessImpl.java
package com.business;
import java.util.ArrayList;
import java.util.List;
import com.data.api.ToDoService;
public class TodoBusinessImpl {
private ToDoService todoService;
TodoBusinessImpl(ToDoService todoService) {
this.todoService = todoService;
}
public List<String> retrieveTodosRelatedToSpring(String s) {
List<String> filteredTodos = new ArrayList<String>();
List<String> allTodos = todoService.retrieveTodos(s);
for (String todo : allTodos) {
if (todo.contains("Spring")) {
filteredTodos.add(todo);
}
}
return filteredTodos;
}
}
Your spec says:
Mockito.when(todoServiceMock.retrieveTodos("Dummy")).thenReturn(todoList);
but your call uses:
todoBusinessImpl.retrieveTodosRelatedToSpring("Ranga");
"Ranga" isn't "Dummy", therefore your spec isn't matched; therefore mockito returns the default result (which would be an empty list).
Try replacing the "Dummy" in Mockito.when(todoServiceMock.retrieveTodos("Dummy")).thenReturn(todoList); with anyString() (import static org.mockito.ArgumentMatchers.anyString;). This did the trick for me.

Getting 500 error while testing webflux code with wiremock

I have spring webflux app with user controller class with end point "/user and user service class.The user service class making call to external api. I am trying to test the service class using wiremock and junit 5 to mock out external api.. However I am getting below error ->
021-07-30 18:22:52.511 ERROR 16974 --- [o-auto-1-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] threw exception
java.net.ConnectException: Connection refused
Code is uploaded at path : https://github.com/neeleshsethi/wiremockdemp/tree/master
It seems it cannot find controller as adding a print statement in controller is not printing anything. Below is the code ->
#Service
public class UserService {
#Autowired
WebClient webClient;
public Mono<User> createuser(User user) {
return webClient.post()
.uri("/usercreate")
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(user))
.retrieve()
.bodyToMono(User.class);
}
}
WireMock Inti class:
package com.example.wiremockdemo;
import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.event.ContextClosedEvent;
import java.util.Map;
public class WireMockInit implements ApplicationContextInitializer<ConfigurableApplicationContext> {
#Override
public void initialize(ConfigurableApplicationContext applicationContext) {
WireMockServer wireMockServer = new WireMockServer(new WireMockConfiguration().dynamicPort());
wireMockServer.start();
applicationContext.addApplicationListener( applicationEvent ->
{
if(applicationEvent instanceof ContextClosedEvent)
{
wireMockServer.stop();
}
}
);
applicationContext.getBeanFactory().registerSingleton("wireMockServer", wireMockServer);
TestPropertyValues.of("externalBaseUrl",wireMockServer.baseUrl())
.applyTo(applicationContext);
}
}
test class:
package com.example.wiremockdemo;
import com.example.wiremockdemo.model.User;
import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.client.WireMock;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.http.MediaType;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.web.reactive.function.BodyInserters;
import reactor.core.publisher.Mono;
import java.awt.*;
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#ContextConfiguration(initializers = {WireMockInit.class})
class WiremockdemoApplicationTests {
#Autowired
WebTestClient webTestClient;
#Autowired
private WireMockServer wireMockServer;
#LocalServerPort
private Integer port;
#Test
void createUsertest() {
System.out.println("Creating stub");
wireMockServer.stubFor(
WireMock.post("/usercreate")
.willReturn(
aResponse()
.withHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE)
.withBodyFile("response.json"))
);
byte[] temp = webTestClient.post()
.uri("http://localhost:" + port + "/user")
// .uri("/user")
.contentType(MediaType.APPLICATION_JSON)
//.accept(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(createUser()))
.exchange()
.expectBody()
.returnResult()
.getResponseBody();
String s = new String(temp);
System.out.println("Response :" +s);
}
public User createUser()
{
return User.builder()
.firstName("neel")
.age(32)
.id(1234)
.build();
}
}
Change this line to:
TestPropertyValues.of(Map.of("externalBaseUrl", wireMockServer.baseUrl()));
This is the correct way to set test properties.

Resources