I'm testing a Spring Boot Service, and there's one pretty much weird function that needs to be tested. I've made a test that runs successfully, but I'm not getting much coverage. Here's a function I'm testing:
protected String setQueryListField(List<String> model, String fieldName) {
String query = "";
if (model.contains("is blank") && model.size() > 1) {
for (String value : model) {
if (value.equals("is blank")) {
query = query.concat(" AND (" + fieldName + " = null");
} else if (model.size() == 2) {
query = query.concat(" OR " + fieldName + " CONTAINS('" + value + "'))");
} else {
if (model.indexOf(value) == 1) {
query = query.concat(" OR " + fieldName + " CONTAINS('" + value + "', ");
} else if ((model.indexOf(value) + 1) == model.size()) {
query = query.concat("'" + value + "'))");
} else {
query = query.concat("'" + value + "', ");
}
}
}
} else if (model.contains("is blank") && model.size() == 1) {
query = query.concat(" AND " + fieldName + " = null");
} else {
query = query.concat(" AND " + fieldName + " CONTAINS('" + String.join("','", model) + "')");
}
return query;
}
And here is a test I wrote. It runs successfully, as I said, but I'd like to get more coverage. Do you have any suggestions?
#Test
#DisplayName("setQueryListField Test")
void setQueryListField() {
List<String> stringList = new ArrayList<>();
stringList.add("is blank");
VaultService vaultService = Mockito.spy(vaultServiceTest);
doReturn("", "").when(vaultService).setQueryListField(stringList, "field__name");
String response = vaultService.setQueryListField(stringList, "field__name");
System.out.println(response);
stringList.add("test");
String secondResponse = vaultService.setQueryListField(stringList, "external__c");
System.out.println(secondResponse);
}
You are only covering the following if block
else if (model.contains("is blank") && model.size() == 1) {
query = query.concat(" AND " + fieldName + " = null");
}
If you need more coverage you need to try with other inputs so that it covers other branches too. For example, with model.size() > 1.
Also, the following lines are no op as it's mocking the same function that you are trying to test.
VaultService vaultService = Mockito.spy(vaultServiceTest);
doReturn("", "").when(vaultService).setQueryListField(stringList, "field__name");
String response = vaultService.setQueryListField(stringList, "field__name");
Related
I've made a test of a getStudies method, that has a private method call inside itself. Now, how to mock that call in a test method (see down below)?
It's on a second line in a method for testing String query = setQueryForChangingState(filterParams);. I'll provide additional code, if necessary.
Method for testing
public Object getStudies(FilterInputModel filterParams) {
String query = setQueryForChangingState(filterParams);
logger.info("Get studies query: " + query);
LinkedMultiValueMap<String, String> queryMap = new LinkedMultiValueMap<>();
queryMap.add("q", query);
return Objects.requireNonNull(webClient.post()
.uri("/query")
.header(HttpHeaders.AUTHORIZATION, getSessionId())
.body(BodyInserters.fromMultipartData(queryMap))
.retrieve()
.bodyToMono(QueryResponse.class)
.block())
.data;
}
Private method
private String setQueryForChangingState(FilterInputModel filterParams) {
String query = "SELECT id, " +
"basf_study_id__cr.name__v, " +
"name__v, " +
"state__v, " +
"bas_core__cr.name__v, " +
"object_type__vr.name__v, " +
"external__c, " +
"contract_laboratory__cr.name__v, " +
"object_type__v " +
"FROM study__c " +
"WHERE object_type__vr.name__v = 'External Study' " +
"AND contract_laboratory__c != null " +
"AND state__v = 'study_setup_completed_state__c'";
if (!filterParams.getCores().isEmpty()) {
query = query + " AND bas_core__c CONTAINS('" + String.join("','", filterParams.getCores()) + "')";
}
if (!filterParams.getStudyStartDate().isEmpty()) {
if (filterParams.getStudyStartDate().size() == 1) {
query = query + " AND study_start_date__c = '" + filterParams.getStudyStartDate().get(0) + "'";
} else if (filterParams.getStudyStartDate().size() == 2) {
query = query + " AND study_start_date__c BETWEEN '" + filterParams.getStudyStartDate().get(0) + "' AND '" + filterParams.getStudyStartDate().get(1) + "'";
} else {
logger.info("Date range has to many inputs!");
}
}
return query;
}
My test
#Test
#DisplayName("Test getStudies")
void getStudies() throws IOException {
Path filePath = Path.of("src/test/resources/__files/jsonFile.json");
String body = Files.read(filePath.toFile(), Charset.defaultCharset());
wireMockServer.stubFor(post(urlEqualTo("/api/v16.1/query"))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/json")
.withBody(body))
);
List<String> cores = List.of("core");
List<String> dates = List.of("startDate");
List<String> objectTypes = List.of("objectType");
inputModel = new FilterInputModel(cores,dates, "state",objectTypes,
"area","analytMethod", "wp", "subDesc", "analytMonitor", "ecoMonitor",
"subType", "analytNeeded", "8e6a2", "methodAvailable",
"analytPhase", "subAvailable","subShipped", "external",
"uploadValidator","contractLab");
Object response = vaultServiceTest.getStudies(inputModel);
QueryResponse jsonBody = new ObjectMapper().readValue(body, QueryResponse.class);
assertEquals(response, jsonBody.data);
I guess it could be done, but I'm not sure how.
protected void saveData() {
Map<String, String> allStationsParams = new HashMap<>();
List<String> stations = getAllStations();
stmt = Database.getUpdateableStatement();
today = (SysTime.currentTimeMillis() / DasStamp.TICKS_PER_DAY) *
DasStamp.TICKS_PER_DAY;
String changeTimestamp = DasStamp.asCompactString(today);
String keyName = "COM.MAPPINGTOOLTIP." + attributeValue;
for (int row = 0; row < this.getTableModel().getRowCount(); row++) {
String station = (String)this.getTableModel().getValueAt(row, 0);
putInStationParams(this, station, allStationsParams, row);
}
for (String station : stations) {
boolean sendToDB = false;
try (ResultSet rs = this.rsParameters) {
rs.beforeFirst();
while (rs.next()) {
if (rs.getString("station").equals(station)) {
sendToDB = true;
break;
}
}
if (sendToDB) {
if (!rs.getString("value_text").equals(allStationsParams.get(station)) || !allStationsParams.containsKey(station)) {
sendToDB = true;
} else {
sendToDB = false;
}
} else if (allStationsParams.containsKey(station)) {
sendToDB = true;
}
if (sendToDB) {
String sql = "REPLACE INTO dss_parameter (key_name, station, valid_from, value_text"
+ ", change_timestamp) VALUES ('"
+ keyName + "','" + station + "','" + DasStamp.asDateOnlyString(today) + "','"
+ Helper.nz(allStationsParams.get(station)) + "','"
+ changeTimestamp + "') ;";
if (null != stmt) {
stmt.execute(sql);
if (!isResultSetEmpty(rs) && !rs.isAfterLast()) {
AdminLogger.log("dss_parameter", Action.UPDATE,
"key_name='" + keyName + "' and station='" + station + "' and valid_from='" + DasStamp.asDateOnlyString(today) + "'",
"value_text='" + rs.getString("value_text") + "'",
"value_text='" + Helper.nz(allStationsParams.get(station)) + "', change_timestamp='" + changeTimestamp + "'");
} else {
AdminLogger.log("dss_parameter", Action.INSERT,
"key_name='" + keyName + "' and station='" + station + "' and valid_from='" + DasStamp.asDateOnlyString(today) + "'",
"", "value_text='" + Helper.nz(allStationsParams.get(station)) + "', change_timestamp='" + changeTimestamp + "'");
}
}
}
} catch (SQLException e) {
AppFrame.msgBox("Error on insert: " + e.getMessage());
Helper.printMessage(true, false, "Parameter save failed!!", e);
}
}
}
where rsParameters is class level and is fetched before. After first
iteration, rsParameters values is getting null.Is this a problem with try
with resource block? Please help
where rsParameters is class level and is fetched before. After first
iteration, rsParameters values is getting null.Is this a problem with try
with resource block? Please help
Your rsParameters parameter is of Type Resultset.
In first iteration, after try{} block is complete close() method of rsParameters:ResultSet is called.
This internally makes all the properties of resultSet NUll.
That is the reason for getting Null properties during second iteration.
SEE: http://grepcode.com/file/repo1.maven.org/maven2/mysql/mysql-connector-java/5.1.27/com/mysql/jdbc/ResultSetImpl.java#ResultSetImpl.realClose%28boolean%29
I have a palette who's model is populated by a user search of customers. This works perfectly when searching initially, however once a customer is selected and the user continues to search for more customers to select a NPE is thrown.
Code from .tml
<t:palette t:id="custSelect" model="customerModel" t:encoder="stringValueEncoder"
availableLabel="Search Results" t:selected="custSelected" value="custSelected">
${custSelected}
</t:palette>
Coresponding .java
Object listResults(List<TbgWebIntCustomer> customers) {
log.debug("LISTRESULTS");
customerList = new ArrayList<String>();
if (customerList != null) {
customerList.clear();
if (request.isXHR()) {
ajaxResponseRenderer.addRender(resultZone);
}
}
String result;
log.debug("LISTRESULTS2 " + customers.size());
for (int i = 0; i <= customers.size() - 1; i++) {
log.debug("counter: " + i);
TbgWebIntCustomer currentCustomer = customers.get(i);
String customerNumber = currentCustomer.getCustomerId();
// Remove leading zeros
String customerName = currentCustomer.getLocationName();
result = customerNumber + " - " + customerName + " - "
+ currentCustomer.getCity();
log.debug(result);
customerList.add(result);
}
log.debug("LISTRESULTS3");
log.debug("customer list size: " + customerList.size());
getCustomerModel();
log.debug("customermodel after customerlist: "
+ getCustomerModel().size());
if (customerList.size() == 100) {
resultsMessage = "Search returned over 100 results. Showing top 100.";
log.debug(resultsMessage);
} else {
String numResults = Integer.toString(customerList.size());
resultsMessage = "Search returned " + numResults + " customers";
log.debug(resultsMessage);
}
log.debug("LISTRESULTS4");
log.debug("customerModel returns at i 0: " + getCustomerModel().get(0));
return request.isXHR() ? resultZone.getBody() : null;
}
Note: getCustomerModel() returns getCustomerList().
I understand that NPEs in Palette happen when one of the selected options is not present in the model you passed to it however I can't identify where it is I'm doing this. I can post setupRender() code if necessary, just trying to keep OP compact.
How can I add in my return findSingleOrNoItem() at the end of the statement to display the for loop counter getClassName() and getAbsolutePercentage() in the findSingleOrNoItem() statement? The reason I added a counter, some will have 4 values of getClassName() and getAbsolutePercentage() and some will have 6 values? so this will depend on the cosModel that gets passed on setParameter 1.
#Override
public TrafficProfile getTrafficProfileByCosClassAllocationNew(CosModel cosModel, Direction direction,
List<ClassOfServiceAllocation> cosClassAllocation, RouterType routerType) throws Exception {
EntityManager em = getEntityManager();
logger.info("Starting getTrafficProfileByCosClass2Allocations cos2 " );
Query query = em.createNativeQuery(buildTrafficProfileByCosClassAllocationQueryNew(cosModel, direction, cosClassAllocation, routerType), TrafficProfile.class);
query.setParameter(1, cosModel.name());
query.setParameter(2, direction.name());
int i= 2;
for(ClassOfServiceAllocation alloc : cosClassAllocation){
query.setParameter(i++, alloc.getClassName());
query.setParameter(i++, alloc.getAbsolutePercentage());
}
return findSingleOrNoItem(query, "Traffic_Profile", "cos_model = " + cosModel.name() + ", direction = " + direction.name() + ?;
}
I am following this existing code below but this is only for cos6. I will have both cos4 and cos6 so I can't hard coded.
#Override
public TrafficProfile getTrafficProfileByCosClassAllocations(Direction direction,
ClassOfService6Allocations cosClassAllocation, RouterType routerType) throws Exception {
EntityManager em = getEntityManager();
logger.info("Starting getTrafficProfileByCosClass6Allocations cos6" );
Query query = em.createNativeQuery(buildTrafficProfileByCosClassAllocationsQuery(direction, cosClassAllocation, routerType), TrafficProfile.class);
query.setParameter(1, "cos6");
query.setParameter(2, direction.name());
query.setParameter(3, cosClassAllocation.getCos1());
query.setParameter(4, cosClassAllocation.getCos2V());
query.setParameter(5, cosClassAllocation.getCos2());
query.setParameter(6, cosClassAllocation.getCos3());
query.setParameter(7, cosClassAllocation.getCos4());
query.setParameter(8, cosClassAllocation.getCos5());
return findSingleOrNoItem(query, "Traffic_Profile", "cos_model = cos6, direction = " + direction.name() + " cos1 = " + cosClassAllocation.getCos1()
+ " cos2v = " + cosClassAllocation.getCos2V() + " cos2 = " + cosClassAllocation.getCos2()
+ " cos3 = " + cosClassAllocation.getCos3() + " cos4 = " + cosClassAllocation.getCos4() + " cos5 = " + cosClassAllocation.getCos5() );
}
Assuming that your ClassOfService6Allocations and supposedly ClassOfService4Allocations inherit from ClassOfServiceAllocation you can check, inside your for-loop, what is the type of the current object and then cast to this class, for instance:
for(ClassOfServiceAllocation alloc : cosClassAllocation) {
if (alloc instanceof ClassOfService6Allocations) {
ClassOfService6Allocations alloc6 = (ClassOfService6Allocations) alloc;
//set your parameters using the alloc6 object
} else if (alloc instanceof ClassOfService4Allocations) {
ClassOfService4Allocations alloc4 = (ClassOfService4Allocations) alloc;
//set your parameters using the alloc4 object
}
How can I split a flat string based on 0102**? string tokenizer is working for only **. Is there any way to split based on 0102**? Please suggest
Here is my complete method
private String handleCibil(InterfaceRequestVO ifmReqDto, String szExtIntType) throws MalformedURLException, org.apache.axis.AxisFault, RemoteException {
/* Declaration and initiliazation */
ConfVO confvo = ifmReqDto.getExtConfVo();
String szResponse = null;
String cibilResponse = null;
String errorResponse = null;
String endpointURL = null;
long timeOut = confvo.getBurMgr().getBurInfo(szExtIntType).getTimeOut();
endpointURL = formWebServiceURL(confvo, szExtIntType);
URL url = new URL(endpointURL);
log.debug("Input xml for cibil "+ifmReqDto.getIfmReqXML());
BasicHttpStub stub= new BasicHttpStub(url,new org.apache.axis.client.Service());
szResponse = stub.executeXMLString(ifmReqDto.getIfmReqXML());
//szResponse=szResponse.replaceAll("&", "&");
log.debug("szResponse "+szResponse);
/* Validate if the obtained response is as expected by IFM */
try {
extDao = new ExtInterfaceXMLTransDAO(ifmReqDto.getSemCallNo(), ifmReqDto.getIdService());
extDao.updateRqstRespXML10g(ifmReqDto.getInterfaceReqNum(), szResponse, GGIConstants.IFM_RESPONSE);
//log.debug("CIBIL_RESPONSE_XPATH " + GGIConstants.CIBIL_RESPONSE_XPATH);
Document xmlDocument = DocumentHelper.parseText(szResponse);
String xPath = GGIConstants.RESPONSE_XPATH;
List<Node> nodes = xmlDocument.selectNodes(xPath);
for (Node node : nodes) {
String keyValue = node.valueOf(GGIConstants.RESPONSE_XPATH_KEY);
// log.debug("keyValue : " + keyValue);
if (keyValue.equalsIgnoreCase(GGIConstants.RESPONSE_XPATH_KEY_VALUE)) {
// log.debug("node value : " + node.getText());
cibilResponse = node.getText();
}
}
log.debug("cibilResponse " + cibilResponse);
String errorResponseXPATH = GGIConstants.CIBIL_ERROR_RESPONSE_XPATH;
List<Node> errorResponseNode = xmlDocument.selectNodes(errorResponseXPATH);
for (Node node : errorResponseNode) {
errorResponse = node.getText();
}
log.debug("errorResponse " + errorResponse);
if(cibilResponse!=null && cibilResponse.length()>0)
{
StringTokenizer cibilResponseResults = new StringTokenizer(cibilResponse,"**");
String tempResponse="";
ArrayList probableMatchList = new ArrayList();
while (cibilResponseResults.hasMoreElements()) {
tempResponse = (String) cibilResponseResults.nextElement();
if(tempResponse.length()>=80)
{
String memberRefNo = tempResponse.substring(69, 80).replaceAll(" ", "");
log.debug("memberRefNo " + memberRefNo);
if (memberRefNo.length() > 0) {
if (Integer.parseInt(memberRefNo) > 0) {
cibilResponse = tempResponse;
cibilResponse = cibilResponse+"**";
}
else
{
probableMatchList.add(tempResponse+"**");
}
}
else
{
probableMatchList.add(tempResponse+"**");
}
}
else
{
cibilResponse = tempResponse+"**";
}
}
log.debug("After finding the Member reference number cibilResponse " + cibilResponse);
log.debug("After finding the Probable reference list " + probableMatchList);
// TKN 008
cibilResponse=StringEscapeUtils.unescapeXml(cibilResponse).replaceAll("[^\\x20-\\x7e]","");
ifmReqDto.setIfmTransformedResult(cibilResponse);
ifmReqDto.setProbableMatchList(probableMatchList);
}
if (errorResponse!=null && errorResponse.length()>0) {
throw new GenericInterfaceException(errorResponse
+ " for the seq_request " + ifmReqDto.getSeqRequest() + " Seq_Interface_req is >> "
+ ifmReqDto.getInterfaceReqNum(),
GGIConstants.SEND_REQUEST_CONSTANT + Strings.padStart(String.valueOf(ifmReqDto.getIdService()), 2, GGIConstants.DEFAULT_NUMBER_STRING)
+ GGIConstants.CIBIL_ERROR_CODE);
}
else if (cibilResponse==null || StringUtils.isEmpty(cibilResponse) ) {
throw new GenericInterfaceException("Cibil TUEF response is empty >> cibil Service "
+ "for the seq_request " + ifmReqDto.getSeqRequest() + "Seq_Interface_req is >> "
+ ifmReqDto.getInterfaceReqNum(),
GGIConstants.SEND_REQUEST_CONSTANT + Strings.padStart(String.valueOf(ifmReqDto.getIdService()), 2, GGIConstants.DEFAULT_NUMBER_STRING)
+ GGIConstants.INTERFACE_ERROR_RESPONSE);
}
/* Setting Instinct response to ifmReqDto object */
} catch (SQLException e) {
log.error("SQLException while connecting to DataBase. Exception message is ", e);
throw new GenericInterfaceException("SQLException >> Instinct Service "
+ "for the seq_request " + ifmReqDto.getSeqRequest() + "Seq_Interface_req is >> "
+ ifmReqDto.getInterfaceReqNum(),
GGIConstants.SEND_REQUEST_CONSTANT + Strings.padStart(String.valueOf(ifmReqDto.getIdService()), 2, GGIConstants.DEFAULT_NUMBER_STRING)
+ GGIConstants.DB_OPERATION_ERROR);
} catch (GenericInterfaceException exp) {
log.error("Exception occured while valid:", exp);
throw exp;
} catch (Exception exp) {
log.error("Exception occured while valid:", exp);
throw new GenericInterfaceException("GeneralException >> Instinct Service "
+ "for the seq_request " + ifmReqDto.getSeqRequest() + "Seq_Interface_req is >> "
+ ifmReqDto.getInterfaceReqNum(),
GGIConstants.SEND_REQUEST_CONSTANT + Strings.padStart(String.valueOf(ifmReqDto.getIdService()), 2, GGIConstants.DEFAULT_NUMBER_STRING)
+ GGIConstants.UNKNOWN_ERROR);
}
return szResponse;
}
I recommend checking out the Java documentation, it provides a really good reference to start with. The .split method uses a regex to split up a string based on a delimiter.
String[] tokens = myString.split("0102\\*\\*");
For now I suspect that you forgot to escape * in split regex.
Try maybe
String[] resutl = yourString.split("0102\\*\\*");
In case you want * to represent any character then use . instead of *
String[] resutl = yourString.split("0102..");
In case you want * to represent any digit use \\d instead
String[] resutl = yourString.split("0102\\d\\d");
String string = "blabla0102**dada";
String[] parts = string.split("0102\\*\\*");
String part1 = parts[0]; // blabla
String part2 = parts[1]; // dada
Here we have a String: "blabla0102**dada", we call it string. Every String object has a method split(), using this we can split a string on anything we desire.
Do you mean literally split by "0102**"? Couldn't you use regex for that?
String[] tokens = "My text 0102** hello!".split("0102\\*\\*");
System.out.println(tokens[0]);
System.out.println(tokens[1]);