getting null in mock object - java

I am trying to mock a object in the junit test file. I am getting value in test file
public void TestMethod() throws SQLException{
String projectID = "Test";
Connection connectionMock = Mockito.mock(Connection.class);
PreparedStatement preparedStatementMock = Mockito.mock(PreparedStatement.class);
ResultSet resultSetMock = Mockito.mock(ResultSet.class);
mockStatic(Manager.class);
Worker workerMock = Mockito.mock(Worker.class);
mockingDetails(workerMock);
mock(PreparedStatement.class);
mock(ResultSet.class);
when(workerMock.getProjectId())
.thenReturn(projectID);
when(Manager.getDatabaseConnection())
.thenReturn(connectionMock);
when(connectionMock.prepareStatement(""))
.thenReturn(preparedStatementMock);
when(preparedStatementMock.executeQuery())
.thenReturn(resultSetMock);
//mockStatic(Manager.class);
System.out.println("workerMock--------->"+workerMock);
System.out.println("prepared stmt--------->"+preparedStatementMock);
assertNotNull(service.getProtocol());
}
If I print here I am getting value worker and prepared statement like this value
"Mock for Worker, hashCode: 853323835"
If I print same in my real method, I am getting null for both worker and prepared statement. I have used annotations
#RunWith(PowerMockRunner.class)
#PrepareForTest(Manager.class)
in the test class
public String Method() throws SQLException
{
Connection conn = Manager.getDatabaseConnection();
String protocol = null;
StringBuilder qryBuilder = new StringBuilder("MyQuery");
qryBuilder.append("condition = ?");
System.out.println("worker.getProjectId()------------->"+worker);
System.out.println("connection------------->"+conn);
PreparedStatement pst = conn.prepareStatement(qryBuilder.toString());
System.out.println("pst------------->"+pst);
pst.setString(1, worker.getProjectId());
try {
ResultSet rset = pst.executeQuery();
try {
while (rset.next()) {
protocol = rset.getString(1);
}
rset.close();
} finally {
pst.close();
}
} catch (SQLException e) {
throw e;
}
return protocol;
}

Related

What is the right way to deal with the PreparedStatement in the Java program flow?

There are two methods in which the PreparedStatement is used.
The first method is called in the second method.
First method:
protected List<String> findResultsByMandantId(Long mandantId) {
List<String> resultIds = new ArrayList<>();
ResultSet rs;
String sql = "SELECT result_id FROM results WHERE mandant_id = ?";
PreparedStatement statement = getPreparedStatement(sql, false);
try {
statement.setLong(1, mandantId);
statement.execute();
rs = statement.getResultSet();
while (rs.next()) {
resultIds.add(rs.getString(1));
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
return resultIds;
}
Second method:
protected void findResultLineEntityToDelete(Long mandantId, String title, String context) {
List<String> resultIds = findResultsByMandantId(mandantId);
String [] resultIdsArr = resultIds.toArray(String[]::new);
ResultSet rs;
//String sql = "SELECT * FROM resultline WHERE result_id in (SELECT result_id FROM results WHERE mandant_id =" + mandantId + ")";
String sql = "SELECT * FROM resultline WHERE result_id in (" + String.join(", ", resultIdsArr)+ ")";
PreparedStatement statement = getPreparedStatement(sql, false);
try {
statement.execute();
rs = statement.getResultSet();
while (rs.next()) {
if (rs.getString(3).equals(title) && rs.getString(4).equals(context)) {
System.out.println("Titel: " + rs.getString(3) + " " + "Context: " + rs.getString(4));
}
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
The class in which both methods are located extends the JDBCBaseManager.
JDBCBaseManager:
private final String url = "jdbc:mysql://localhost:3306/database";
private final String userName = "root";
private final String password = "";
private Connection connection = null;
private PreparedStatement preparedStatement = null;
private int batchSize = 0;
public JDBCBaseManager() {
// Dotenv env = Dotenv.configure().directory("./serverless").load();
// url = env.get("DB_PROD_URL");
// userName = env.get("DB_USER");
// password = env.get("DB_PW");
}
public void getConnection() {
try {
if (connection == null) {
connection = DriverManager.getConnection(url, userName, password);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public PreparedStatement getPreparedStatement(String sql, boolean returnGeneratedKeys) {
try {
if (connection == null) {
getConnection();
}
if (preparedStatement == null) {
if (!returnGeneratedKeys) {
preparedStatement = connection.prepareStatement(sql);
} else {
preparedStatement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
connection.setAutoCommit(false);
}
}
return preparedStatement;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public void closeConnection() {
try {
if (connection != null && !connection.isClosed()) {
System.out.println("Closing Database Connection");
connection.close();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public void startBatch(int batchSize) throws SQLException {
connection.setAutoCommit(false);
setBatchSize(batchSize);
}
public void commit() {
try {
if (connection != null && !connection.isClosed()) {
connection.commit();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public int getBatchSize() {
return batchSize;
}
public void setBatchSize(int batchSize) {
this.batchSize = batchSize;
}
The ResultSet in the second method still contains the results from the first method.
I already tried to close the connection and open it again before the second method is executed, but then I get the errors:
java.sql.SQLException: No operations allowed after statement closed.
java.sql.SQLNonTransientConnectionException: No operations allowed
after connection closed.
Can you tell me how to deal with the statement correctly in this case? Is my BaseManager incorrectly structured?
Here lies the error
public JDBCBaseManager() {
private PreparedStatement preparedStatement = null;
public PreparedStatement getPreparedStatement(String sql, boolean returnGeneratedKeys) {
try {
......
if (preparedStatement == null) {
if (!returnGeneratedKeys) {
preparedStatement = connection.prepareStatement(sql);
} else {
preparedStatement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
connection.setAutoCommit(false);
}
}
return preparedStatement;
You build the prepare statement only the first time the method getPreparedStatement is called because only the first time the field preparedStatement is null. Every next time you call the method getPreparedStatement you receive the previous preparedStatement from the previous SQL and not the new one.
Remove the check for if (preparedStatement == null) {
You need to build a new preparedStatement every time you want to execute a new SQL.

Ambiguous behavior of ResultSet

I have a requirement to create separate POJO which will set/get sql ResultSet and use its methods throughout my project code like below. I have created below 2 classes
public class Tester3
{
public MyResultSet test() throws SQLException{
MyResultSet mrs = new MyResultSet();
PreparedStatement ps = null;
String values = null;
boolean flag = false;
String one = "'12'";
String two = "'jt'";
String a = null;
String b = null;
try {
if(flag==true)
{
values = "'3%'";
a =null;
b = "OR id IN(\'" +a+ "\')";
}else
{
values = "'%'";
a = one + "," + two;
b = "AND id IN("+a+")";
}
String sql = "SELECT * FROM veracodetable where orts like PARAM RAMAN";
sql = sql.replaceFirst("PARAM", values);
sql = sql.replaceFirst("RAMAN", b);
System.out.println("SQL: "+sql);
ps = new Connection1().getConnection().prepareStatement(sql);
ps.executeQuery();
mrs.setRs(ps.executeQuery());
System.out.println("ResultSet: "+mrs.getRs().next());
} catch (SQLException e) {
e.printStackTrace();
}
return mrs;
}
public static void main(String[] args) throws SQLException {
Tester3 t = new Tester3();
MyResultSet rs = t.test();
System.out.println("ResultSet: "+rs.getRs().next());
}
}
public class MyResultSet {
ResultSet rs = null;
public ResultSet getRs() {
return rs;
}
public void setRs(ResultSet rs) {
this.rs = rs;
}
}
When executed above code with separate POJO MyResultSet, I don't get any result in ResultSet. However if I skip POJO implementation and use resultSet directly, I am able to get results.
Is rs.getRs() invoking at all? If not, why?
I would separate the statements as they dont't perform the same function, and then populate;
PreparedStatemet ps = null;
ResultSet rs = null;
if(flag){
String stmt = "...?...?";
ps = con.preparedStatement(stmt);
ps.setString(0,a);
ps.setString(1,b);
rs = ps.executeQuery;
}else{
String stmt = "...?...?";
ps = con.preparedStatement(stmt);
ps.setString(0,a);
ps.setString(1,b);
rs = ps.executeQuery;
}
}

Findbugs error "Load of known null value" SQL connection

I have DAO class with methods getting and sending data.
I'm catching Exceptions inside SQL requests, so I need to declare connection variables outside of try parenthesis.
every method looks lookes like this:
public Role getRole(int roleId) {
Connection connection = null;
ResultSet rs = null;
PreparedStatement statement = null;
Role role = null;
try {
connection = dataSource.getConnection();
statement = connection.prepareStatement("select ROLE_ID, ROLE_TEXT from ROLES WHERE ROLE_ID = :1");
statement.setInt(1, roleId);
rs = statement.executeQuery();
rs.next();
role = roleMapper.mapRow(rs, 1);
} catch (SQLException e) {
} finally {
JdbcUtils.closeResultSet(rs);
JdbcUtils.closeStatement(statement);
JdbcUtils.closeConnection(connection);
return role;
}
}
But there's problem. Finbugs giving me an error, saying:
Load of known null value in DAO.getRole
and
may fail to clean up java.sql.Statement
So what should I do to avoid that?
The getRole can return null.
Furthermore:
if (rs.next()) {
role = roleMapper.mapRow(rs, 1);
}
I prefer another notation. And the error solution unfortunately consists of either letting getRole throw an exception (best) or letting return an Optional<Role>
//public Role getRole(int roleId) throws SQLException {
public Optional<Role> getRole(int roleId) {
try (Connection connection = dataSource.getConnection();
PreparedStatement statement =
connection.prepareStatement(
"select ROLE_ID, ROLE_TEXT from ROLES WHERE ROLE_ID = :1")) {
statement.setInt(1, roleId);
try (ResultSet rs = statement.executeQuery()) {
if (rs.next()) {
return roleMapper.mapRow(rs, 1);
}
}
} catch (SQLException e) { //
Logger.getLogger(getClass().getName()).log(Level.SEVERE, "ID: " + roleId, e); //
}
return Optional.empty(); //
}

Data Access Object class getting SQLServerException

I'm getting the following execption when executing sql statements
SQLServerException: The server failed to resume the transaction.
Desc:69d00000016.
I know that the following DAO implementation is not correct. I want to know what is the correct implementation for the following code and if the fact that my connFactory is declared as static can cause the above error.
private static DbConnectionFactory connFactory;
protected myDAO() {
myDAO.connFactory = DbConnectionFactoryHome.getHome().lookupFactory("facName");
}
public myReturn myAccessMethod(final int cod) throws BaseException {
Connection conn = null;
CallableStatement stmt = null;
ResultSet resSet = null;
myReturn ret= null;
try {
conn = myDAO.connFactory.getConnection();
stmt = conn.prepareCall("{call name (2)}");
stmt.setInt(1, cod);
resSet = stmt.executeQuery();
if (resSet.next()) {
ret = new myReturn(resSet.getInt("someValue"));
}
}
catch (SQLException sqle) {
throw new myException(sqle.getMessage(), (Throwable)sqle);
}
finally {
try {
if (resSet != null) {
resSet.close();
}
if (stmt != null) {
stmt.close();
}
if (conn != null) {
conn.close();
}
}
}
return ret;
}
Should I remove the static modifier from the connFactory or implement a singleton, so when the constructor is called again the factory is not recreated?
I would make your DBConnectionFactory a singleton. A good example of how to do this can be found here: Singleton DB Connectionfactory.
However, I am not sure that the your issue is with the db connection factory being static. It may actually be with the way you are extracting results with the result set. Make sure you process all your results. You should include a more complete stack trace. You may want to look into why you are getting: "The server failed to resume the transaction." There is an article about how what causes this error and how to fix it here: Failed to resume transaction
Try doing something like this:
CallableStatement stmt = connection.prepareCall("{call name (2)}");
stmt.setInt(1, cod);
stmt.execute();
ResultSet rs = (ResultSet)stmt.getObject(index);
//Loop results
while (rs.next()) {
ret = new myReturn(resSet.getInt("someValue")
}

simple data comparison with MySQL, nullpointerexception

I'm currently being thrown into the depths by my school and they are expecting me to program a simple login form using sql. They have given us brief examples on how they use JDBC and what it all is, but haven't really explained step by step how to use it on our own. Therefore i have snatched a bit of code from an example but i'm unable to get it working. I keep receiving an nullpointerexception and i can't figure out why :(
Here's the connection class:
package Database;
import java.sql.*;
public class MySQLConnection {
public static final String DRIVER = "com.mysql.jdbc.Driver";
public static final String DBURL = "jdbc:mysql://localhost/corendon";
public static final String DBUSER = "root";
public static final String DBPASS = "simplepass";
private ResultSet result = null;
private int affectedRows = -1;
Connection conn = null;
public void startConnection() {
try {
Class.forName(DRIVER);
DriverManager.setLoginTimeout(5);
conn = DriverManager.getConnection(DBURL, DBUSER, DBPASS);
} catch (Exception e) {
}
}
public void closeConnection() {
try {
if (conn != null && !conn.isClosed()) {
conn.close();
}
} catch (Exception e) {
}
conn = null;
}
public ResultSet performSelect(PreparedStatement prdstmt) throws SQLException {
result = prdstmt.executeQuery();
return result;
}
public int performUpdate(PreparedStatement prdstmt) throws SQLException {
affectedRows = prdstmt.executeUpdate();
return affectedRows;
}
public Connection getConnection() {
return conn;
}
}
And here is the method i'm getting the exception in (in a different class):
MySQLConnection conn = new MySQLConnection();
public void compareData(int id, String pass) throws SQLException{
ResultSet rs = null;
PreparedStatement prdstmt = null;
String query = "SELECT id, password FROM users WHERE id=?, password=?";
conn.startConnection();
prdstmt = conn.getConnection().prepareStatement(query);
prdstmt.setInt(1, id);
prdstmt.setString(2, pass);
rs = conn.performSelect(prdstmt);
while (rs.next()){
String tempPass = rs.getString("password");
int tempId = rs.getInt("id");
}
if(conn != null){
conn.closeConnection();
}
}
I'm getting the nullpointerexception on line:
prdstmt = conn.getConnection().prepareStatement(query);
Why does it throw an exception there, but not when i start the connection and also how do i solve this? Thanks in advance.
When you call startConnection(), you are throwing an Exception
public void startConnection() {
try {
Class.forName(DRIVER);
DriverManager.setLoginTimeout(5);
conn = DriverManager.getConnection(DBURL, DBUSER, DBPASS);
} catch (Exception e) {
//An exception occurs here, but you don't do anything about it
}
}
Therefore, when you call getConnection(), the conn variable is still null, which is throwing the NullPointerException.
Either make startConnection() throw an exception so that you're forced to deal with it (this is usually how most JDBC drivers work anyway), or check to see if the conn variable is null before you start using it.
public void compareData(int id, String pass) throws SQLException{
ResultSet rs = null;
PreparedStatement prdstmt = null;
String query = "SELECT id, password FROM users WHERE id=?, password=?";
conn.startConnection();
if (conn.getConnection() == null) {
throw new SQLException("Connection is null!");
}
Or (what I think would personally be better)
public void startConnection() throws Exception {
Class.forName(DRIVER);
DriverManager.setLoginTimeout(5);
conn = DriverManager.getConnection(DBURL, DBUSER, DBPASS);
}
public void compareData(int id, String pass) throws SQLException{
ResultSet rs = null;
PreparedStatement prdstmt = null;
String query = "SELECT id, password FROM users WHERE id=?, password=?";
try {
conn.startConnection();
} catch (Exception e) {
throw new SQLException(e);
}
Also as a tip, you should probably avoid declaring your classes as the same name of other classes you are using. This is all happening in your own MySQLConnection class, but that could be confusing with the actual com.mysql.jdbc.MySQLConnection class.

Categories