asked on
Refactor For loop with Six if loops to better unit test
I have a method which takes Json object with for loop and then 6 if conditions like below
public void doTransaction(ProductSt productStMessage){
List<Serial> listOfItems= ProductAdapter.parseJsonProductMessage(productStMessage);
....
...
for(int index=0; index<listOfItems,size();index++){
if(listOfItems.get(index).getItemName().equals("Smpl"){
if(listOfItems.get(index).getItemValueText()!=null){
productId=listOfItems.get(index).getItemValueText().toString();
}
else{ productId=null}
}
if(listOfItems.get(index).getItemName().equals("Xyz"){
if(listOfItems.get(index).getItemValueText()!=null){
productCd=listOfItems.get(index).getItemValueText().toString();
} else{ productCd=null}
}
if(listOfItems.get(index).getItemName().equals("Abc"){
if(listOfItems.get(index).getItemValueText()!=null){
productDes=listOfItems.get(index).getItemValueText().toString();
} else{ productDec=null}
}
if(listOfItems.get(index).getItemName().equals("Cde"){
if(listOfItems.get(index).getItemValueText()!=null){
productLoc=listOfItems.get(index).getItemValueText().toString();
} else{ productLoc=null}
}
if(listOfItems.get(index).getItemName().equals("Fgh"){
if(listOfItems.get(index).getItemValueText()!=null){
productShelf=listOfItems.get(index).getItemValueText().toString();
} else{ productShelf=null}
}
if(listOfItems.get(index).getItemName().equals("Ijk"){
if(listOfItems.get(index).getItemValueText()!=null){
productRow=listOfItems.get(index).getItemValueText().toString();
}else{ productRow=null}
}
I like to refactor this code so that I can unit test each individual values coming based on Xpath kind of values coming from Json message. When I try to do using Intellij Idea by selecting entire for loop got error saying too many variables there. Please advise
ASKER
{
productCd = getItemValue();
}
Above method only has one argument where as below method has 2 arguments right
public String itemNameEquals(Serial serial, String name)
{
return serial.getItemName().equal
}
Also below should returns list of Serial custom objects instead of simple Serial custom object as below?
List<Serial> listOfItems= ProductAdapter.parseJsonPr
ASKER
ASKER
The reason I go rid of the traditional loop was because you were doing a get() over and over again which is ver inefficient. You are doing a list scan every time. You could reduce that to one call to be more efficient but the advanced loop makes it just go through the list once.
For the arguments you are right. I forgot to include the serial object in my call, it should be passed in
ASKER
public void doTransaction(ProductSt productStMessage){
List<Serial> listOfItems= ProductAdapter.parseJsonProductMessage(productStMessage);
String productID=null;
String productCd=null;
String productDec=null;
String productLoc=null;
String productShelf=null
boolean productPresentIndicator=false;
for(int index=0; index<listOfItems,size();index++){
if(listOfItems.get(index).getItemName().equals("Smpl"){
if(listOfItems.get(index).getItemValueText()!=null){
// productId=listOfItems.get(index).getItemValueText().toString();
productId=getProductId(listOfItems,productID,index)
}
// else{ productId=null}
}
if(listOfItems.get(index).getItemName().equals("Xyz"){
if(listOfItems.get(index).getItemValueText()!=null){
// productCd=listOfItems.get(index).getItemValueText().toString();
productCd=getProductCd(listOfItems,productID,index)
// } else{ productCd=null}
}
if(listOfItems.get(index).getItemName().equals("Abc"){
if(listOfItems.get(index).getItemValueText()!=null){
// productDes=listOfItems.get(index).getItemValueText().toString();
productDec=getProductDec(listOfItems,productID,index)
//} else{ productDec=null}
}
if(listOfItems.get(index).getItemName().equals("Cde"){
if(listOfItems.get(index).getItemValueText()!=null){
// productLoc=listOfItems.get(index).getItemValueText().toString();
productLoc=getProductLoc(listOfItems,productID,index)
//} else{ productLoc=null}
}
if(listOfItems.get(index).getItemName().equals("Fgh"){
if(listOfItems.get(index).getItemValueText()!=null){
//productShelf=listOfItems.get(index).getItemValueText().toString();
productShelf=getProductShelf(listOfItems,productID,index)
// } else{ productShelf=null}
}
if(listOfItems.get(index).getItemName().equals("Ijk"){
if(listOfItems.get(index).getItemValueText()!=null){
//productPresentIndicator=listOfItems.get(index).getItemValueText().toString();
productPresentIndicator=getProductId(listOfItems,productID,index)
// }else{ productRow=null}
}
pubic String getProductID(List<Serial> listOfItems, String productID, int index){
if(listOfItems.get(index).getItemValueText()!=null){
productID=listOfItems.get(index).getItemValueText().toString)
}
else{
productID=null;
}
return productID;
}
pubic String getProductCd(List<Serial> listOfItems, String productID, int index){
...
}
pubic String getProductDec(List<Serial> listOfItems, String productID, int index){
...
}
pubic String getProductLoc(List<Serial> listOfItems, String productID, int index){
...
}
pubic String getProductShelf(List<Serial> listOfItems, String productID, int index){
..
}
pubic boolean getProductPresentIndicator(List<Serial> listOfItems, String productID, int index){
...
}
I updated like above.I like to refactor whole for loop with 5 for if loops that deals with String to be returned and last if loop deals with boolean type to be returned. This refactored method should take listOfItems as input(which obtained from productStMessage original argument of original parent doTransaction() method and return some data structure/collection object including those 5 Strings, 1 boolean value
ASKER
public void doTransaction(ProductSt productStMessage){
List<Serial> listOfItems= ProductAdapter.parseJsonProductMessage(productStMessage);
....
...
Serial thisSerial;
String itemName;
for(int index=0; index<listOfItems,size();index++){
thisSerial = listOfItems.get(index);
itemName = thisSerial.getItemName().toString();
switch (itemName){
case "Smpl":
productID = thisSerial.getItemValueText()!=null?thisSerial.getItemValueText().toString():null;
break;
case "Xyz":
productCd = thisSerial.getItemValueText()!=null?thisSerial.getItemValueText().toString():null;
break;
case "Ijk":
productRow = thisSerial.getItemValueText()!=null?thisSerial.getItemValueText().toString():null;
break;
.
.
.
}
}
}
Hope that's more like it.
If I were you I would start by breaking your function apart in to small functions. Have your functions do a small amount of work that returns something that can be tested. I would then probably put your whole for loop in its own function that returns an object that could be tested apart. I don't really understand the underlying concept of your code, so in my example I named it something unrealistic. Something like:
Open in new window
Hope this makes sense our helps. But it seems like the biggest problem to making your function untestable is that it is doing way too much