The following is a Java (Hibernate) Method. How can I write a test for it? I want the test method to return a SQL statement.The code reference a lot of other classes and packages which already exist. Ignore these and just show me how to integrate them in my test program.
#Override
public AppTacticalSubUnit returnByCode(String code) throws MyOwnDAOException {
Session session = getSession();
UnitOfWork unitOfWork = new UnitOfWork();
try {
unitOfWork.beginTransaction(session);
Criteria criteria = session.createCriteria(AppTacticalSubUnit.class);
criteriaAppTacticalSubUnit.add(Restrictions.eq("code", code));
criteriaAppTacticalSubUnit.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
setJoinFetches(criteria);
AppTacticalSubUnit ret = (AppTacticalUnit) criteria.uniqueResult();
unitOfWork.commit();
return ret;
} catch (HibernateException e) {
unitOfWork.rollback();
throw new ObelixxDAOException(e.getMessage(), e);
}
}
private void setJoinFetches(Criteria criteria) {
criteria.setFetchMode("appTacticalUnit.spaceOpsAreaServiceType", FetchMode.JOIN);
criteria.setFetchMode("appTacticalSubUnit.spaceOpsAreaServiceType.assExternalServiceType", FetchMode.JOIN);
criteria.setFetchMode("appTacticalSubUnit.spaceOpsAreaServiceType.assExternalServiceType.lookupServiceType", FetchMode.JOIN);
criteria.setFetchMode("appTacticalSubUnit.spaceOpsAreaServiceType.assExternalServiceType.lookupExternalServiceType", FetchMode.JOIN);
criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
criteria.addOrder(Order.asc("name"));
I have started something like this:
package na.co.sab.vitalix.db.dao;
import org.hibernate.Criteria;
import org.hibernate.FetchMode;
import org.hibernate.HibernateException;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.hsqldb.Session;
import na.co.sab.datashare.util.UnitOfWork;
import na.co.sab.vitalix.db.exception.MyOwnDAOException;
import na.co.sab.vitalix.db.util.HibernateOltpSessionUtil;
public class AppTacticalSubUnitTest {
//protected static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AppOTacticalSubUnitTest.class);
static protected HibernateOltpSessionUtil dataShareInstance;
public static void initializeVitalixOnHsql() throws Exception {
initializeVitalixOnHsql(true);
Have a look at this article http://java.dzone.com/articles/how-get-jpqlsql-string seems like it describes what you want.
The idea is to use org.hibernate.Query#getQueryString() method.
Related
I'm trying to make an insert and get the auto generated id returned. This is an Oracle database. For that i am using org.apache.commons.dbutils.QueryRunner insert which returns the first column.
The problem is i don't know for which reason i am getting added a parameter in the query and it won't let it work.
I have this code:
import javax.annotation.Nonnull;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.Optional;
#Singleton
public class ConceptToBonusRepository extends GenericSQLRepository{
private static final String QUERY_SAVE_CONCEPT_TO_BONUS = "INSERT INTO concept_to_bonus (ID, CONCEPT_ID, CONCEPT_TYPE)" +
" VALUES (SEQ_CONCEPT_TO_BONUS_ID.NEXTVAL,?,?)";
#Inject
public ConceptToBonusRepository(#Named("OracleDataSource") #Nonnull DataSource dataSource) {
super(dataSource);
}
public Optional<Long> saveConceptToBonus(ConceptToBonus conceptToBonus)
try {
return Optional.ofNullable(
runInsert(
QUERY_SAVE_CONCEPT_TO_BONUS, conceptToBonus.getConceptId(), conceptToBonus.getConceptType()
)
);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
and my GenericlSQLRepository
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import javax.annotation.Nonnull;
import javax.sql.DataSource;
import java.sql.SQLException;
public abstract class GenericSQLRepository {
private QueryRunner queryRunner;
private ScalarHandler<Long> autogeneratedIdHandler = new ScalarHandler<>();
protected GenericSQLRepository(#Nonnull final DataSource dataSource) {
this.queryRunner = new QueryRunner(dataSource);
}
protected Long runInsert(#Nonnull final String sql,
Object... args) throws SQLException {
return queryRunner.insert(sql, this.autogeneratedIdHandler, args);
}
}
When i try to run this i get this error
"java.sql.SQLException: Wrong number of parameters: expected 3, was given 2 Query: INSERT INTO concept_to_bonus (ID, CONCEPT_ID, CONCEPT_TYPE) VALUES (SEQ_CONCEPT_TO_BONUS_ID.NEXTVAL,?,?) Parameters: [1731472066, ORDER]"
I really don't understand why is it adding a parameter in the parameter count. When i run this insert with a simple execute, it works just fine
I have a static class which has this method:
public static Connection getDbConnection(String tenant, String product) {
Connection connection = null;
try {
Map<String,Map<String,String >> databaseConnectionTable = PropertyUtil.getInstance().getDatabaseConnectionTable();
Map<String,String> properties = getHighestPrecedenceMap(databaseConnectionTable,tenant,product);
if (properties!=null) {
Class.forName(properties.get("db.driver"));
connection = DriverManager.getConnection(
properties.get("db.url"),
properties.get("db.user"),
properties.get("db.password"));
}
} catch (ClassNotFoundException e) {
LOGGER.error("Message",e);
} catch (SQLException e) {
LOGGER.error("Message:",e);
}
return connection;
}
Then I have another class which has a method for fetching the resultset given a SQL Query String, this method calls the above method, below is the source:
public static ResultSet getResultSetFromSql(String sql,String tenant,String product) {
Connection connection = null;
PreparedStatement statement = null;
ResultSet rs = null;
try {
if(product!=null)
connection = SqlConnectionUtil.getDbConnection(tenant,product);
RccSqlParameterMap parameterMap = RccSqlParameterMap.getParameterMap();
if(connection!=null) {
if (parameterMap.getSqlParameters().entrySet().size() > 0)
sql = parameterMap.SqlMessageFormat(sql);
else
LOGGER.error("Parameter map isn't set please initialize it");
LOGGER.info("Executing SQL: " + sql);
statement = connection.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY);
if (!statement.execute()) {
LOGGER.error("No results found for statement!");
return null;
}
rs = statement.getResultSet();
}else{
LOGGER.error("Coudn't create Connection Object");
}
} catch (SQLException e) {
LOGGER.error("Message", e);
}
return rs;
}
I need to write unit tests for testing these, to have an in memory implementation I am able to mock the result set, by reading the rows from files, so when I instantiate the result set mocker and do getResultSet() I get the result set object, the problem I am facing is integrating this mocker with the above methods. Please suggest a way to do this.
You can specify mock data right in the code of test case, there's no need to read something from the file system.
With Mockito you can make methods of the objects to return whatever you want:
// Initialize the object to be returned
ResultSet desiredResultSet = ...;
// After doing this you can mock methods of statement object
statement = Mockito.mock(PreparedStatement.class);
// Whenever you call statement.getResultSet(), it will return desiredResultSet
Mockito.doReturn(desiredResultSet).when(statement).getResultSet();
The only thing you need to change in your code to use this mechanism is to make Connection available to your test code. So that you can mock it's method that returns PreparedStatement the same way like I've demonstrated above.
In overall, I'd recommend you to split your methods to a bunch of smaller ones - right now they have too many things going on for just one method. This will also make your code much easier to unit test and mock.
With your current implementation it's impossible to mock connection object, since Mockito unable to mock static calls, that is possible with PowerMockito. There is possible solution (feel free to change test logic, it's just a worked skeleton with mocks for you)
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import java.util.Map;
import java.util.HashMap;
#RunWith(PowerMockRunner.class)
#PrepareForTest({ SqlConnectionUtil.class, RccSqlParameterMap.class })
public class TestQueryRunner {
#Test
public void testGetResultSetFromSql() throws SQLException {
ResultSet rs = mock(ResultSet.class);
when(rs.getString(eq("foo"))).thenReturn("This is mocked value");
PreparedStatement stmt = mock(PreparedStatement.class);
when(stmt.getResultSet()).thenReturn(rs);
when(stmt.execute()).thenReturn(true);
Connection connection = mock(Connection.class);
when(connection.prepareStatement(anyString(), anyInt(), anyInt()))
.thenReturn(stmt);
PowerMockito.mockStatic(SqlConnectionUtil.class);
PowerMockito.when(SqlConnectionUtil.getDbConnection(anyString(), anyString()))
.thenReturn(connection);
Map<String, String> sqlParams = new HashMap<>();
sqlParams.put("param1", "value1");
RccSqlParameterMap paramMap = mock(RccSqlParameterMap.class);
when(paramMap.getSqlParameters()).thenReturn(sqlParams);
PowerMockito.mockStatic(RccSqlParameterMap.class);
PowerMockito.when(RccSqlParameterMap.getParameterMap()).thenReturn(paramMap);
ResultSet actual = QueryRunner.getResultSetFromSql("SELECT ...",
"tenant", "product");
assertEquals(rs, actual);
assertEquals("This is mocked value", actual.getString("foo"));
}
}
Also, some general advices:
Always use {} in each if-else statements even if they are one-lined. This will be much more convenient to merge and support your code in the future.
Override your code to manage database connections properly. They should be closed! Use some third-party connection pooling mechanism like Apache DBCP
Hope it helps!
I have a web application I am making using a websocket API to handle the websockets, here is the code for that part
package comm2.hello;
import java.io.IOException;
import java.util.ArrayList;
import javax.websocket.OnClose;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.apache.catalina.session.*;
#ServerEndpoint(value = "/echo")
public class wschat {
private static ArrayList<Session> sessionList = new ArrayList<Session>();
#OnOpen
public void onOpen(Session session) {
try {
sessionList.add(session);
// asynchronous communication
session.getBasicRemote().sendText("hello");
} catch (IOException e) {
}
}
public void send(String text, Session session) throws IOException {
session.getBasicRemote().sendText(text);
}
}
I am trying to have another java class then call into the send method to send messages, using the following code.
package comms;
import java.io.IOException;
import java.util.ArrayList;
import javax.websocket.Session;
import javax.websocket.Session;
import comm2.hello.*;
public class main {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
wschat h = new wschat();
String text = "hello";
//session shouldn't be null but not sure what to make it
Session session = null;
h.send(text,session);
}
}
As you can see, I have the session variable in the main.java class set to null which will thus always produce a null pointer error. This is because I am not sure what to make session equal to, does anyone have any idea what to initialize the session variable to in main.java?
I am getting a NullPointerException on AlertService#findAll() method:
java.lang.NullPointerException
com.t2.claims.services.AlertService.findAll(AlertService.java:24)
com.t2.claims.controllers.AlertIndexController.doAfterCompose(AlertIndexController.java:28)
This is the findAll() method:
public List<Alert> findAll() {
Query query = new Query(where("id").exists(true));
return mongoTemplate.find(query, Alert.class);
}
The whole AlertService is as such:
package com.t2.claims.services;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.t2.claims.models.Alert;
import static org.springframework.data.mongodb.core.query.Criteria.where;
#Service("alertService")
#Transactional
public class AlertService {
#Resource(name="mongoTemplate")
private MongoTemplate mongoTemplate;
public List<Alert> findAll() {
Query query = new Query(where("id").exists(true));
return mongoTemplate.find(query, Alert.class);
}
public void add(Alert alert) {
try {
mongoTemplate.insert(alert);
} catch(Exception e) {}
}
public void update(Alert alert) {
Query query = new Query(where("id").is(alert.getId()));
try {
Update update = new Update();
update.set("assignedUser", alert.getAssignedUser());
update.set("status", alert.getStatus());
update.set("category", alert.getCategory());
update.set("vehicleStatus", alert.getVehicleStatus());
update.set("brand", alert.getBrand());
mongoTemplate.updateMulti(query, update, Alert.class);
} catch(Exception e) {}
}
public void delete(Alert alert) {
try {
Query query = new Query(where("id").is(alert.getId()));
// Run the query and delete the entry
mongoTemplate.remove(query, Alert.class);
} catch(Exception e) {}
}
}
It may be easier to check out my IntegrateMongo branch on Github to have at look in more detail. https://github.com/georgeotoole/T2ClaimsPortal/tree/IntegrateMongo
I can't understand if there is an issue with my code or perhaps mongo on my machine .. ?
Thanks
I'm pretty certain it's a case of... :
#Resource(name="mongoTemplate")
private MongoTemplate mongoTemplate;
...not being injected.
What about adding a null check in the methods that use mongoTemplate to make sure that it has been injected?
public List<Alert> findAll() {
Query query = new Query(where("id").exists(true));
if (mongoTemplate == null) {
throw new IllegalStateException("mongoTemplate is null");
}
return mongoTemplate.find(query, Alert.class);
}
hello:
I'm writing code in java for nutch(open source search engine) to remove the movments from arabic words in the indexer.
I don't know what is the error in it.
Tthis is the code:
package com.mycompany.nutch.indexing;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.io.Text;
import org.apache.log4j.Logger;
import org.apache.nutch.crawl.CrawlDatum;
import org.apache.nutch.crawl.Inlinks;
import org.apache.nutch.indexer.IndexingException;
import org.apache.nutch.indexer.IndexingFilter;
import org.apache.nutch.indexer.NutchDocument;
import org.apache.nutch.parse.getData().parse.getData();
public class InvalidUrlIndexFilter implements IndexingFilter {
private static final Logger LOGGER =
Logger.getLogger(InvalidUrlIndexFilter.class);
private Configuration conf;
public void addIndexBackendOptions(Configuration conf) {
// NOOP
return;
}
public NutchDocument filter(NutchDocument doc, Parse parse, Text url,
CrawlDatum datum, Inlinks inlinks) throws IndexingException {
if (url == null) {
return null;
}
char[] parse.getData() = input.trim().toCharArray();
for(int p=0;p<parse.getData().length;p++)
if(!(parse.getData()[p]=='َ'||parse.getData()[p]=='ً'||parse.getData()[p]=='ُ'||parse.getData()[p]=='ِ'||parse.getData()[p]=='ٍ'||parse.getData()[p]=='ٌ' ||parse.getData()[p]=='ّ'||parse.getData()[p]=='ْ' ||parse.getData()[p]=='"' ))
new String.append(parse.getData()[p]);
return doc;
}
public Configuration getConf() {
return conf;
}
public void setConf(Configuration conf) {
this.conf = conf;
}
}
I think that the error is in using parse.getdata() but I don't know what I should use instead of it?
The line
char[] parse.getData() = input.trim().toCharArray();
will give you a compile error because the left hand side is not a variable. Please replace parse.getData() by a unique variable name (e.g. parsedData) in this line and the following lines.
Second the import of
import org.apache.nutch.parse.getData().parse.getData();
will also fail. Looks a lot like a text replace issue.