I'm trying to learn how to use Mockito and i'm hung up on how to go about verifying a method on a certain object was called X amount of times.
I have the following test code
verify(record, times(1)).setValue(Mockito.any(String.class),Mockito.any(String.class));
and the following piece of production code i'm trying to test
The string[]'s i'm setting up to iterate through
protected String[] columnNames = {"_id", "created_at", "updated_at", "name"};
protected ColumnType[] columnTypes = {ColumnType.INTEGER, ColumnType.TIMESTAMP, ColumnType.TIMESTAMP, ColumnType.TEXT};
and the production code that's in a loop, iterating through the String[]
for (int i = 0; i < columnCount; i++) {
if (columnNames[i].equals("_id")) {
record.setId(cursor.getInt(0));
} else {
switch (columnTypes[i]) {
case BOOL:
record.setValue(columnNames[i], cursor.getInt(i));
break;
case TEXT:
record.setValue(columnNames[i], cursor.getString(i));
break;
case INTEGER:
record.setValue(columnNames[i], cursor.getInt(i));
break;
case TIMESTAMP:
record.setValue(columnNames[i], cursor.getLong(i));
break;
case LONG:
record.setValue(columnNames[i], cursor.getLong(i));
break;
case DOUBLE:
record.setValue(columnNames[i], cursor.getDouble(i));
break;
default:
record.setValue(columnNames[i], "");
break;
}
}
}
And this is the error i get
testDataSourceCanFindRecord(com.test.app.DataSourceTest) Time
elapsed: 0.081 sec <<< FAILURE!
org.mockito.exceptions.verification.TooManyActualInvocations:
customer.setValue(, ); Wanted 1 time:
-> at com.test.app.DataSourceTest.testDataSourceCanFindRecord(DataSourceTest.java:141)
But was 3 times. Undesired invocation:
-> at com.test.core.DataSource.cursorToRecord(DataSource.java:210)
I'm expecting record.setValue(String key, String value) to be called once because of the "name" field in the String[]. What's happening is Mockito is registering record.setValue(String key, Long value) as the same thing as record.setValue(String key, String value), which is incorrect. Line 210 is the setValue in the TIMESTAMP case. How can i correct this?
If you look at the source code for InvocationMatcher, it looks like the logic to check method equality is a little more generous than you might think, and could ignore method overloading in some circumstances.
I'm not 100% sure, but try replacing any(String.class) (which accepts any object of any type) with isA(String.class), which will filter out invocations where that parameter is not a String. (anyString only checks its type in Mockito 2.0 and beyond.) Counterintuitively, any(Foo.class) does not mean "anything as long as it's a Foo", it means "anything". This is due to change in Mockito 2.0.
Of course, you could also tighten up your verification so it checks that the key or value is equal to an expected value, but I'm not sure how possible that is in your case.
Related
When I'm comparing an EditText's value with a String var in java, it is going to else part.
case 2 is not executing, every time default case is executing
sem=(EditText)findViewById(R.id.csem);
sem1=sem.getText().toString();
switch (sem1) {
case "2":
c = 1;
i.putExtra("fees", c);
startActivity(i);
break;
default:
Toast.makeText(details.this, "Enter valid current sem", Toast.LENGTH_SHORT).show();
break;
Since it is a String, you should compare it using equals method
// Gets the value of the EditText
String value = ((EditText) findViewById(R.id.csem)).getText().toString();
if(value.equals("2")) {
// Do your things
}
switch statement on String objects is a new feature introduced in Java 1.7. Unfortunatelly Android requires version 1.6 or 1.5. This is why you have to forget for some time about such constructions.
You can avoid using if-statements-chain by storing the map of methods which will be executed for certain String: Map. You can always encapsulate Method it with some Handler object. Look here for more info: How to remove large if-else-if chain
and
why-cant-i-switch-on-a-string
Not sure if I've missed something really obvious. I know for sure that my String is as follows:
1This is a test message
I'm trying to detect whether the first character is '1', so here's some of my code:
//This outputs '1'
Toast noCmd = Toast.makeText(Play.this, decodedMessage.substring(0,1), Toast.LENGTH_SHORT);
noCmd.show();
if (decodedMessage.charAt(0) == 1) {
noCmd = Toast.makeText(Play.this, "This should show up", Toast.LENGTH_SHORT);
noCmd.show();
noCmd = Toast.makeText(Play.this, finalMessage + " from " + sender, Toast.LENGTH_SHORT);
noCmd.show();
}
if (decodedMessage.substring(0,1) == "1") {
noCmd = Toast.makeText(Play.this, "This should show up", Toast.LENGTH_SHORT);
noCmd.show();
noCmd = Toast.makeText(Play.this, finalMessage + " from " + sender, Toast.LENGTH_SHORT);
noCmd.show();
}
As you can see, I'm trying two methods to get the toasts inside the if statement to show up. Weirdly, when the code is run, only the top (unconditional) toast displays.
Any ideas?
For the first one, the char is '1'. What's currently happening in your code is that because you're comparing a char with an integer, the char is being converted to an int using its character code. For a 1, that comes out as 49, which is not equal to the integer 1. You need to compare the char you're retrieving from the String with the char representing a digit "1", and that means you need to write it as '1'.
For the second one, you need to use .equals() to test for String equality, rather than ==. If you take two String objects s and t that have the same content, then you still will find that s==t will come out as false, unless they happen to be pointing at the same bit of memory (i.e., they're the same instance). To check whether they have the same content, you check
s.equals(t)
rather than
s==t
So, in summary, make the first one
if (decodedMessage.charAt(0) == '1') {
//toast stuff
}
and the second one
if ("1".equals(decodedMessage.substring(0,1))) {
//toast stuff
}
The reason, by the way, for not writing
if (decodedMessage.substring(0,1).equals("1")) {
//toast stuff
}
instead is that if the String on which you call .equals() is null then you'll end up with a NullPointerException, which usually you want to avoid. Actually in this case it would be fine, because the substring() call won't return null, but in the general case if you want to test whether s and "something" are equal then you use
"something".equals(s)
rather than
s.equals("something")
just in case s is null.
1 is an integer with value 1. If you want the ASCII 1, use '1' in single quotes which has the integer value of 49.
For comparing strings, use equals() and not ==. See How do I compare strings in Java?
To compare strings you need to use equals method:
if("1".equals(decodedMessage.charAt(0))){
}
I'm trying to do a calculator with the 4 basic operations. I started using doubles to get the arguments from edittext, but I discovered the problem with decimal values. To avoid that, I used BigDecimal, but now the app is failing at some specific numbers, as 1/(1.1). I noticed only the divide function is wrecking the app, add,sub and multiply are working fine. I really would appreciate some help with this. Here's part of the code:
div.setOnClickListener(
new View.OnClickListener(){
#Override
public void onClick(View v){
if(! num1 .getEditableText().toString().matches("") && !num2 .getEditableText().toString().matches(""))
{String valor1 =num1.getText().toString();
String valor2 =num2.getText().toString();
BigDecimal a = new BigDecimal(valor1);
BigDecimal b = new BigDecimal(valor2);
BigDecimal result = a.divide(b);
Toast.makeText(MainActivity.this,"="+result, Toast.LENGTH_LONG).show();
} }
});
If the quotient has a nonterminating decimal expansion and the operation is specified to return an exact result, an ArithmeticException is thrown. Otherwise, the exact result of the division is returned, as done for other operations.
Use divide method like that
a.divide(b, 2, RoundingMode.HALF_UP)
where 2 is precision and RoundingMode.HALF_UP is rounding mode
source:https://stackoverflow.com/a/4591216/1589566
It crashes on an ArithmeticException because the result is a number with infinite decimals.
From http://docs.oracle.com/javase/1.5.0/docs/api/java/math/BigDecimal.html
"In the case of divide, the exact quotient could have an infinitely long decimal expansion; for example, 1 divided by 3. If the quotient has a nonterminating decimal expansion and the operation is specified to return an exact result, an ArithmeticException is thrown. Otherwise, the exact result of the division is returned, as done for other operations"
In your country it may be ',' and not '.'
String valor1 = num1.getText().toString().replace('.', ',');
Try this and tell us if it works !
I can't help noticing that I'm using quite a lot of string comparisons while parsing a well defined XML file in Android (with a XmlPullParser).
As of now it typically looks something like this (somewhat simplified):
...
tag = parser.getName().toLowerCase();
if ("tag1".equals(tag)) {
// Do something with the state machine
}
else if ("tag2".equals(tag)) {
// Do something else with the state machine
}
...
else if ("tag23".equals(tag)) {
// Do something more with the state machine
}
What I would like to have instead is something like this (where StringMatcher would be the hypothetical happy-maker for me):
private static final StringMatcher tagMatcher = new StringMatcher(StringMatcher.NO_MATCH);
static {
tagMatcher.addString("tag1", 1);
tagMatcher.addString("tag2", 2);
....
tagMatcher.addString("tag23", 23);
}
...
tag = parser.getName().toLowerCase();
switch (tagMatcher.match(tag)) {
case 1:
// Do something with the state machine
break;
case 2:
// Do something else with the state machine
break;
...
case 23:
// Do something more with the state machine
break;
default:
Log.e("PARSER", "Unexpected tag: " + tag);
break;
}
As you see I would like a UriMatcher pattern applied to my XML file tags. Do any of you know of such a class I can use in Android? Any other fast filtering on strings would do as well (it would be neat, though, if the UriMatcher-pattern could be reused).
So far I've been looking at regular expressions but I'm not really sure I can fit it to my needs (I would like a switch - case style test) and, of course, the regular string comparison as shown in above example.
Cheers,
-- dbm
You can either use a HashMap since that does not need to iterate over the whole array to find the match value
private static final HashMap<String, Integer> tagMatcher =
new HashMap<String, Integer>();
static {
tagMatcher.put("tag1", 1);
tagMatcher.put("tag2", 2);
tagMatcher.put("tag23", 23);
}
private void parse (String node) {
Integer value = tagMatcher.get(node);
int match = value != null ? value.intValue() : 0;
switch (match) {
case 1:
// etc
break;
case 0: // no match
break;
}
}
or you can use a SparseIntArray using the same hash approach. Advantage here is that you don't need to box int into Integer which should result in a slight speed / memory advantage.
private static final SparseIntArray tagMatcher2 = new SparseIntArray();
private static void put(String key, int value) {
tagMatcher2.put(key.hashCode(), value);
}
private static int get(String key) {
return tagMatcher2.get(key.hashCode());
}
static {
put("tag1", 1);
put("tag2", 2);
put("tag23", 23);
}
private void parse2 (String node) {
switch (get(node)) {
case 1:
// etc
break;
case 0: // no match
break;
}
}
This is doing binary search instead of iterating over the whole thing like SparseArray#indexOfValue(t) does. Note that there is a chance of hash collisions in this approach.
I think using an approach like that is faster than a long chain of if (equals) else if (equals) for larger amounts of comparisons. The if .. else if approach needs to check String.equals() every time which boils down to comparing all characters of the strings while a hash based approach needs to calculate the hash value just once and can do a binary search over all known hash values then.
Use a SparseArray
static{
tagmatcher.append(0, "tag1");
tagmatcher.append(1, "tag2");
}
switch(tagmatcher.keyAt(tagmatcher.indexOfValue(tag))){
case 0:
break;
case 1:
break
}
But if you are going to add consecutive indexes you can always use an ArrayList
I'm still pretty new to this, but I'm trying to make a calculator for myself to use at work; similar to a resistor calculator.
I am hope to change a textview and imageview according to the last two digits entered into a edittext box. For example, if I were to type in "9,000,011", I would want to display a certain color of image and text that corresponds with "11" and the same color and text for say 1,000,011. Also different for 12, 13, and so on. this way No matter what number I type it only looks at the last two digits. Does anyone know the way to do this or maybe can just point me in the right direction?
here is how I'm
private void calculate() {
number = Double.parseDouble(inputnumber.getText().toString());
ImageView iv = (ImageView) this.findViewById(R.id.pairimage);
if (number == 6000001) {
iv.setImageResource(R.drawable.white);
txtnumber.setText("White");
} else if (number == 6000002) {
iv.setImageResource(R.drawable.red);
txtnumber.setText("Red");
}
//*and so on, all the way up to 99*
}
If you want just the last two, then I would use
String wholeNumber = inputnumber.getText().toString();
int n = Integer.valueOf(wholeNumber.subString(wholeNumber.length()-2, wholeNumber.length()-1);
and then a switch block:
switch(n) {
case 1:
iv.setImageResource(R.drawable.white);
txtnumber.setText("White");
break;
case 2:
iv.setImageResource(R.drawable.red);
txtnumber.setText("Red");
break;
}
etc.
Maybe convert the number to a String and then look at that e.g.
String theNumber = String.valueOf(number);
String lastTwoDigits =
theNumber.substring(theNumber.length() -2, theNumber.length());
Then you can have your if statements to read the lastTwoDigits. Or convert back to int (Integer.valueOf(lastTwoDigits); and use a switch statement. Or put the values 0-99 into a Map and have a Command object or something as the value which gets executed.
Obviously you'll need some validation here on the user input.
You have a couple of options. The easiest one is to use the modulus operator like:
number = number % 100;
switch (number) {
case 1:
// do stuff;
break;
case 2:
// do stuff;
break;
}
For this to work, though, "number" will have to be an integer. It's an integer in your examples, so that may work for you; otherwise you can try some math tricks like:
int number2 = (int)(number * 100) % 100;
Go with the sub-string approach. I've found that some number combinations don't multiply/divide well in java.