How do I test currency exchange method with API? - java

I have problem with testing my method for currency exchange from API. I have no idea how to do testings to this method as I can't predict what currency rates are at the moment, they are changing every second. My teacher told me that I have to do another method that testing my first one and then Mock something. Please guys help.
public class CurrencyService {
private static HttpURLConnection conn;
private Pattern currencyPattern;
public double exchange(String currencyFrom, String currencyTo, double amount) {
currencyPattern = Pattern.compile("[A-Z]{3}");
if (!currencyPattern.matcher(currencyFrom).matches() || !currencyPattern.matcher(currencyTo).matches()) {
throw new BadPatternForCurrency("Currency FROM and TO must be for example: Dollar USD, euro EUR etc.");
}
if (amount < 0) {
throw new NoMinusValuesInAmountException("Amonut must be more than 0!");
}
DecimalFormat df = new DecimalFormat("##.##");
String adres = "https://api.apilayer.com/exchangerates_data/";
BufferedReader reader;
String line;
StringBuilder responseContent = new StringBuilder();
try {
URL url = new URL(adres + "convert?to=" + currencyTo.toUpperCase() + "&from=" + currencyFrom.toUpperCase() + "&amount=" + amount);
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("apikey", "tSaLWidFRzgzO2mGNfFgVEIr2cqeWCUY");
int status = conn.getResponseCode();
if (status != 200) {
reader = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
while ((line = reader.readLine()) != null) {
responseContent.append(line);
}
reader.close();
} else {
reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
while ((line = reader.readLine()) != null) {
responseContent.append(line);
}
reader.close();
}
} catch (ProtocolException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
JSONObject obj = new JSONObject(responseContent.toString());
double result = obj.getDouble("result");
return result;
}
}

To elaborate on #tgdavies comment:
You should better move everything starting with:
BufferedReader reader; into a separate class, for example, ExchangeApiClient and provide that class into your CurrencyService via a constructor. That ExchangeApiClient should return a string, so everything left to your service is to create a call exchangeApiClient.getResponse().
This way you will be able to unit-test your currency service.
The question remains how to test your ExchangeApiClient - that can also be done. You must create a HttpConnectionFactory and pass that factory via a constructor to your ExchangeApiClient. You should also make it non-static. Then you can pass a mock connection, which returns mock inputStream, you can here more about that here
If you want to read something about mocking I recommend a book "Practical Unit Testing with JUnit and Mockito".

Related

getting a null pointer exception when trying to parse JSON data from a url in a Async Class android

Could someone please explain or correct as to why I am getting a null pointer exception in my Async Class? I am trying to get data from a URL but get a null pointer exception for the 162, which contains the following code
int lengthJsonArr = jsonMainNode.length();
I am not sure as to why that is but if someone could help that would be great. or if someone can show me a better alternative to fetch json data from url that would also be a great help.
public class userTask extends AsyncTask<String, Void, Void>{
HttpURLConnection connection = null;
private String Content;
#Override
protected Void doInBackground(String... urls) {
BufferedReader reader = null;
try {
URL url = new URL(urls[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
InputStream stream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
buffer.append(line);
} Content = buffer.toString();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
#Override
protected void onPostExecute(Void s) {
super.onPostExecute(s);
String OutputData = "";
JSONObject jsonResponse;
try {
jsonResponse = new JSONObject(Content);
JSONArray jsonMainNode = jsonResponse.optJSONArray("Android");
int lengthJsonArr = jsonMainNode.length(); //This is causing the exception
for (int i =0; i < lengthJsonArr; i++) {
JSONObject jsonChildNode = jsonMainNode.getJSONObject(i);
String name = jsonChildNode.optString("name").toString();
Double longitude = jsonChildNode.optDouble("lon");
Double latitude = jsonChildNode.optDouble("lat");
OutputData += " Name : "+ name +" "
+ "Longitude : "+ longitude +" "
+ "Latitude : "+ latitude +" "
+"-------------------------------------------------- ";
//Show Parsed Output on screen (activity)
Toast toast = Toast.makeText(getApplicationContext(), OutputData, Toast.LENGTH_LONG);
toast.show();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
This is not a good way to fetch JSON data in android. You should use Volley or Retrofit library. These libraries will work accuratly and efficiently than normal code.
There are alot of things to take care of while fetching data. All will be done by library. And you just need to write few lines of code.
You can follow many good tutorials on google.
As this works...
jsonResponse = new JSONObject(Content);
...you at least succesfully receive a HTTP response which contains a valid JSON object.
The next line...
JSONArray jsonMainNode = jsonResponse.optJSONArray("Android");
...tries to extract a JSON array, but apparently fails and as a result your jsonMainNode variable is null. That is how optJSONArray() works. It just returns null if it does not find what was asked for. (Instead of throwing a JSONException for example.)
Then the next line...
int lengthJsonArr = jsonMainNode.length();
...of course fails because you can't get the length of a null JSON array.
So it looks like the JSON you receive does not include an array called "Android". You could/should place a breakpoint on...
JSONArray jsonMainNode = jsonResponse.optJSONArray("Android");
...and check what's in the JSON object. Or just print out the response. (And properly name it "content" with lowercase so people won't nag about the Java coding convention...)
As for avoiding the NullPointerException you could use code like:
if (jsonResponse.has("Android")) {
JSONArray jsonMainNode = jsonResponse.optJSONArray("Android");
int lengthJsonArr = jsonMainNode.length();
// Etc.
// ...
}
else {
// TODO: Recover from the situation.
// ...
}

Convert Clob to String

How can I get String out of Clob. I did google it, but
myClob.getSubString(0, (int) info.length()));
is the only thing I get. Console says:
java.sql.SQLException: Invalid argument(s) in call at
oracle.sql.CLOB.getSubString(CLOB.java:278) at
ru.tenet.es09.dao.CompanyDAOImpl.get(CompanyDAOImpl.java:72) at
ru.tenet.es09.dao.CompanyDAOImpl.getList(CompanyDAOImpl.java:132) at
ru.tenet.es09.dao.AddressDAOImpl.getList(AddressDAOImpl.java:59) at
ru.tenet.es09.Test.main(Test.java:11)
It points on getSubString() method. What is wrong?
Assuming you're using standard JDBC, once you have a ResultSet object you should be able to call ResultSet#getString("clob_field_name") to retrieve your CLOB data.
I know I'm late to this party!. Here is the one liner i used from hibernate library. If hibernate is already integrated to project then we can use annotations to convert clob to java String. In my case i had custom result transformer which read data from multiple tables after costly join. In the resultSetTransformer the below line does the job.
ClobType.INSTANCE.toString((Clob) tuple[2])
// org.hibernate.type.ClobType
this my way (sorry my english)
res = ps.executeQuery();
try {
while (res.next()) {
System.out.println(res.getClob(1));//confirm data
sRet = res.getString(1);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
ps.close();
}
Converting String to CLOB
SOobject.setLongStringField( new SerialClob(entityString.toCharArray()));//Converting String to CLOB
Convert Clob to String
public String getLongStringField() {
Reader reader = null;
BufferedReader bufferedReader = null;
try {
reader = longStringField.getCharacterStream();
bufferedReader = new BufferedReader(reader);
return IOUtils.toString(bufferedReader);
} catch (Exception e) {
throw new RuntimeException("Error while reading String from CLOB", e);
} finally {
IOUtils.closeQuietly(reader);
IOUtils.closeQuietly(bufferedReader);
}
}
I have created a java method which can create string from a CLOB object:
public String clobToString(Clob data) {
StringBuilder sb = new StringBuilder();
try {
Reader reader = data.getCharacterStream();
BufferedReader br = new BufferedReader(reader);
String line;
while(null != (line = br.readLine())) {
sb.append(line);
}
br.close();
} catch (SQLException e) {
// handle this exception
} catch (IOException e) {
// handle this exception
}
return sb.toString();
}

Restrict the AutoCompleteTextView predictions to only restaurants

I've got an Android app that allows the user to perform a details search based on a restaurants name. However, depending on the users input, the predictions can contain places, countries, etc. Where can I add a restriction to only check for restaurant names?
My current code:
public static ArrayList<String> autocomplete(String input) {
ArrayList<String> resultList = null;
HttpURLConnection conn = null;
StringBuilder jsonResults = new StringBuilder();
try {
StringBuilder sb = new StringBuilder(PLACES_API_BASE
+ TYPE_AUTOCOMPLETE + OUT_JSON);
sb.append("?key=" + API_KEY);
sb.append("&input=" + URLEncoder.encode(input, "utf8"));
URL url = new URL(sb.toString());
System.out.println("URL: " + url);
conn = (HttpURLConnection) url.openConnection();
InputStreamReader in = new InputStreamReader(conn.getInputStream());
// Load the results into a StringBuilder
int read;
char[] buff = new char[1024];
while ((read = in.read(buff)) != -1) {
jsonResults.append(buff, 0, read);
}
} catch (MalformedURLException e) {
Log.e(LOG_TAG, "Error processing Places API URL", e);
return resultList;
} catch (IOException e) {
Log.e(LOG_TAG, "Error connecting to Places API", e);
return resultList;
} finally {
if (conn != null) {
conn.disconnect();
}
}
try {
// Create a JSON object hierarchy from the results
JSONObject jsonObj = new JSONObject(jsonResults.toString());
JSONArray predsJsonArray = jsonObj.getJSONArray("predictions");
resultList = new ArrayList<String>(predsJsonArray.length());
place = new HashMap<String, String>();
for (int i = 0; i < predsJsonArray.length(); i++) {
// System.out.println(predsJsonArray.getJSONObject(i).getString(
// "description"));
// System.out
// .println("============================================================");
resultList.add(predsJsonArray.getJSONObject(i).getString(
"description"));
String description = predsJsonArray.getJSONObject(i).getString("description");
String placeId = predsJsonArray.getJSONObject(i).getString("place_id");
place.put( description, placeId);
}
} catch (JSONException e) {
Log.e(LOG_TAG, "Cannot process JSON results", e);
}
return resultList;
}
According to place types the closest you can get is the establishment filter. You are going to have to perform a search rather than an autocomplete in order to use the restaurant filter.
Using the Places API for Android PlaceComplete sample I tried passing in Place.TYPE_ESTABLISHMENT and Place.TYPE_RESTAURANT to AutocompleteFilter.create to verify.
Try adding a place_type in your search, use this link to find the supported types.

URLConnection Reading in as null in java

I'm a building a basic program to query Target's API with a store ID and Product ID which returns the aisle location. I think I'm using the URL constructor incorrectly, however (I've had trouble with it in the past and still don't fully understand them). Below is the code I have, redacted the API Key for obvious reasons. The URL I create is valid when put into a browser and no exceptions are thrown but at the the end when I print out the contents of the page it is null. What am I missing? Any help is really appreciated!
package productVerf;
import java.net.*;
import java.io.*;
public class Verify {
public static void main(String args[]) {
// first input is store id second input is product id
String productID = args[0];
String storeID = args[1];
String file = "/v2/products/storeLocations?productId=" + productID
+ "&storeId=" + storeID
+ "&storeId=694&key=REDACTED";
URL locQuery;
URLConnection lqConection = null;
try {
locQuery = new URL("http", "api.target.com", file);
lqConection = locQuery.openConnection();
} catch (IOException e) {
e.printStackTrace();
}
BufferedReader response;
String responseString = "";
try {
response = new BufferedReader(new InputStreamReader(
lqConection.getInputStream()));
while (response.readLine() != null) {
responseString += response.readLine();
}
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(responseString);
}
}
Maybe you are reading only even lines
you are reading a line twice? (in while statement...), it looks you reads the first line which is dropped in while condition test. If your response contains only one line, nothing will be readed
use this:
String line;
while ((line=response.readLine()) != null) {
responseString += line;
}

how to get a value by key from an json (or xml) string?

In the android app I get an xml or json string returned, However, I cant seem to figure out any way on how to get an value from the string in any way by entering an key.
In PHP you just use something like $myArray['parent']['child'] but I have no clue on how this works in java.
Any idea's would be greatly appreciated! (an example for both XML and JSON even more ;) )
Here's what I would do:
locate an XML/JSON library (there's tons) (google-gson for json)
read the documentation to find a parse method ((new JsonParser()).parse(text))
read the documentation to find out what the return value is (JsonElement)
decide what you want to do with the parsed data (myJsonObj.get(...))
write the code
public class parsingjsontest2 extends Activity {
/** Called when the activity is first created. */
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(main);
String str = connect("http://rentopoly.com/ajax.php?query=Bo"));
System.out.println("String::"+str);
}
}
private String connect(String url)
{
// Create the httpclient
HttpClient httpclient = new DefaultHttpClient();
// Prepare a request object
HttpGet httpget = new HttpGet(url);
// Execute the request
HttpResponse response;
// return string
String returnString = null;
try {
// Open the webpage.
response = httpclient.execute(httpget);
if(response.getStatusLine().getStatusCode() == 200){
// Connection was established. Get the content.
HttpEntity entity = response.getEntity();
// If the response does not enclose an entity, there is no need
// to worry about connection release
if (entity != null) {
// A Simple JSON Response Read
InputStream instream = entity.getContent();
// Load the requested page converted to a string into a JSONObject.
JSONObject myAwway = new JSONObject(convertStreamToString(instream));
// Get the query value'
String query = myAwway.getString("query");
**// Make array of the suggestions
JSONArray suggestions = myAwway.getJSONArray("suggestions");
// Build the return string.
returnString = "Found: " + suggestions.length() + " locations for " + query;
for (int i = 0; i < suggestions.length(); i++) {
returnString += "\n\t" + suggestions.getString(i);
}
// Cose the stream.
instream.close();
}
}
else {
// code here for a response othet than 200. A response 200 means the webpage was ok
// Other codes include 404 - not found, 301 - redirect etc...
// Display the response line.
returnString = "Unable to load page - " + response.getStatusLine();
}
}
catch (IOException ex) {
// thrown by line 80 - getContent();
// Connection was not established
returnString = "Connection failed; " + ex.getMessage();
}
catch (JSONException ex){
// JSON errors
returnString = "JSON failed; " + ex.getMessage();
}
return returnString;
}
private static String convertStreamToString(InputStream is) {
/*
* To convert the InputStream to String we use the BufferedReader.readLine()
* method. We iterate until the BufferedReader return null which means
* there's no more data to read. Each line will appended to a StringBuilder
* and returned as String.
*/
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
}
As you didn't specify what kind of xml you are trying to read, I'm answering based on what I know.
In Android, if you were talking about the layout and strings.xml files, you use a dot (.) operator, like R.string.appname.
Please post more details about your specific problem, if this is not what you were looking for.

Categories

Resources