In a junit I have, I get the following reason for failure
java.lang.AssertionError: expected:<1200000> but was:<1.2E+6>
which is essentially the same value. The actual json response is 1200000 when I hit from postman and the method that I am using to get the field for 1200000 has a return type of BigDecimal.
Not sure how to fix this 1.2E+6 as actual.
quite likely you try to compare a BigDecimal to another type and the comparison fail. Please check the javadoc: https://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html#equals(java.lang.Object)
"true if and only if the specified Object is a BigDecimal whose value and scale are equal to this BigDecimal's."
If the 2 numbers are not BigDecimal, you'll get false. If the 2 are Bigdecimal but don't have the same scale, you should use compareTo.
The simplest thing that you can do is to compare it using long value:
assertEquals(new BigDecimal("1.2E+6").longValue(), 1200000);
Or you can use AssertJ to have a nice and tidy BigDecimal assertion:
assertThat(new BigDecimal("1.2E+6")).isEqualByComparingTo(new BigDecimal("1200000"));
//or
assertThat(new BigDecimal("1.2E+6")).isEqualByComparingTo("1200000");
Related
I am trying to execute tests using beanshell assertion. I have a csv file with Expected money amounts which are all to 2 decimal places eg 145.16, 1945.21 etc and i wish to compare them to actual values that will come back from my sampler http response with the same format. I wish my test case to pass if the difference between the two is < 0.1 i.e. 10 cents/pence etc.
I started by parsing the initial string values to doubles or floats or shorts and using Math.abs to compare but of course the accuracy was not there eg if the difference was actually 10 cents(FAIL) the calculation was actually be say 0.999999765 or similar and so the test case would incorrectly PASS.
I have now moved onto BigDecimal with little success. I have tried to use setScale which has made the comparsion a bit more accurate.
So my question is BigDecimal the way to go? What do i do with the BigDecimal after i have created it - if i convert it to a short or float etc i get the same problem again. Would DecimalFormat help ? I need the values to be with two decimal points at the point where i use Math.abs - is there an alternative to Math.abs ?
Hope that makes sense and thanks in advance.
BigDecimal is quite good candidate to go with, at least all Java solutions which are designed to work with money objects are using BigDecimal under the hood. You may find ROUND_HALF_EVEN property useful
Be aware that there is Joda-Money library which provides Money.isGreaterThan() method which can be used instead of custom logic.
Starting from JMeter 3.1 it is recommended to use JSR223 Test Elements and Groovy language for any form of scripting so consider switching to Groovy as soon as it will be possible.
FYI this worked for me in the end -
import java.math.BigDecimal;
BigDecimal Actual_PAF = new BigDecimal("${Actual_PAF}");
BigDecimal Expected_PAF = new BigDecimal("${Expected_PAF}");
BigDecimal ActualPAFDifference = new
BigDecimal(Actual_PAF.subtract(Expected_PAF).toString());
if (ActualPAFDifference.abs() < 0.001)
{ Failure=false;
vars.put("PAFPassOrFail","PASS");}
else
{ Failure=true;
vars.put("PAFPassOrFail","FAIL");
}
I am new to Mockito and trying to cover following source code:
jdbcOperations.update(insertRoleQuery,new Object[]{"menuName","subMenuName","subSubMenuName","aa","bb","cc","role"});
In this query is taking 7 string parameters. I have written the mockito test case for the code and it's also covering the source code but I am not sure whether it's the correct way or not.
when(jdbcOperations.update(Mockito.anyString(), new Object[]{Mockito.anyString(),Mockito.anyString(),Mockito.anyString(),Mockito.anyString(),Mockito.anyString(),Mockito.anyString(),Mockito.anyString()})).thenThrow(runtimeException);
Please suggest if i am doing it right way or not.
Thanks
As per the docs, you can either use exact values, or argument matchers, but not both at the same time:
Warning on argument matchers:
If you are using argument matchers, all arguments have to be provided
by matchers.
If you do mix them, like in your sample, mockito will complain with something similar to
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers!
2 matchers expected, 1 recorded:
-> at MyTest.shouldMatchArray(MyTest.java:38)
This exception may occur if matchers are combined with raw values:
//incorrect:
someMethod(anyObject(), "raw String");
When using matchers, all arguments have to be provided by matchers.
For example:
//correct:
someMethod(anyObject(), eq("String by matcher"));
For more info see javadoc for Matchers class.
In your case you don't seem to care about the array contents, so you can just use any():
when(jdbcOperation.update(anyString(), any())).thenThrow(runtimeException);
If you want to at least check the number of parameters, you can use either
org.mockito.Mockito's argThat(argumentMatcher):
when(jdbcOperation.update(anyString(), argThat(array -> array.length == 7))).thenThrow(runtimeException);
org.mockito.hamcrest.MockitoHamcrest's argThat(hamcrestMatcher):
when(jdbcOperation.update(anyString(), argThat(arrayWithSize(7)))).thenThrow(runtimeException);
If you're interested in matching certain values, you can use AdditionalMatchers.aryEq(expectedArray), or just Mockito.eq(expectedArray) which has a special implementation for arrays, but I fell that the first one expresses your intent in a clearer way.
when(jdbcOperation.update(anyString(), aryEq(new Object[]{"whatever"}))).thenThrow(runtimeException);
My getUserDetails class take User(custome class) and string as arguments and return User. If I use Mockito matcher as below:
when(authService.getUserDetails(any(User.class),anyString())).thenReturn(any(User.class));
It gives me InvalidUseOfMatchersException 2 matchers expected, 3 found. Can't I use the above expression?
Matchers are not used for returning.
.thenReturn(any(User.class));
You have to return something tangible here. Matchers are just for matching up input so that you can dictate what is returned when certain input is provided. You still need to have a real output to return.
You should pass instance of User to thenReturn, not matcher. That User instance will be returned when authService.getUserDetails is invoked.
This code will work:
User user=new User();
when(authService.getUserDetails(any(User.class),anyString())).thenReturn(user));
As there should be a value and not type in thenReturns()
I am testing a Restful endpoint in my JUnit and getting an exception as below in the
list which is present as an argument inside the save method,
**"Argument(s) are different! Wanted:"**
save(
"121",
[com.domain.PP#6809cf9d,
com.domain.PP#5925d603]
);
Actual invocation has different arguments:
save(
"121",
[com.domain.PP#5b6e23fd,
com.domain.PP#1791fe40]
);
When I debugged the code, the code broke at the verify line below and threw the
above exception. Looks like the arguments inside the "testpPList" within the save
method is different. I dont know how it becomes different as I construct them in my
JUNit properly and then RestFul URL is invoked.
Requesting your valuable inputs. Thanks.
Code:
#Test
public void testSelected() throws Exception {
mockMvc.perform(put("/endpointURL")
.contentType(TestUtil.APPLICATION_JSON_UTF8)
.content(TestUtil.convertObjectToJsonBytes(testObject)))
.andExpect(status().isOk());
verify(programServiceMock, times(1)).save(id, testpPList);
verifyNoMoreInteractions(programServiceMock);
}
Controller method:
#RequestMapping(value = "/endpointURL", method = RequestMethod.PUT)
public #ResponseBody void uPP(#PathVariable String id, #RequestBody List<PPView> pPViews) {
// Code to construct the list which is passed into the save method below
save(id, pPList);
}
Implementing the Object#equals(Object) can solve it by the equality comparison. Nonetheless, sometimes the object you are validating cannot be changed or its equals function can not be implemented. For such cases, it's recommended using org.mockito.Matchers#refEq(T value, String... excludeFields). So you may use something like:
verify(programServiceMock, times(1)).save(id, refEq(testpPList));
Just wrapping the argument with refEq solves the problem.
Make sure you implement the equals method in com.domain.PP.
[Edit]
The reasoning for this conclusion is that your failed test message states that it expects this list of PP
[com.domain.PP#6809cf9d, com.domain.PP#5925d603]
but it's getting this list of PP
[com.domain.PP#5b6e23fd, com.domain.PP#1791fe40]
The hex values after the # symbol for each PP object is their hash codes. Because they are different, then it shows that they belong to different objects. So the default implementation of equals will say they're not equal, which is what verify() uses.
It's good practice to also implement hashCode() whenever you implement equals(): According to the definition of hashCode, two objects that are equal MUST have equal hashCodes. This ensures that objects like HashMap can use hashCode inequality as a shortcut for object inequality (here, placing objects with different hashCodes in different buckets).
The order of the parameters for Assert.assertEquals method in JUnit is (expected, actual)
Although in another thread someone said that is for no reason, in one of my Java classes in Uni the professor mentioned a specific reason of that ordering, but I don't remember it.
Anybody can help me out with this?
Proper labeling in tools/failure results - The tools are following this order and some GUI tools will label which value is the expected value and which value is the actual value. At the very least, it will minimize confusion if the labels match the values; at worst, you spend time/effort tracking down the wrong issue trying to trace the source of the actual value that wasn't actually the actual value.
Consistency across assertEquals usage - If you aren't consistent in your order throughout your assertions, you can confuse future-you (or other future maintainer) if the values are swapped arbitrarily from case-to-case, again lending to potential confusion.
Consistent parameter ordering across assert methods - It may be reversible for assertEquals, but the order may matter for other assert* methods (in JUnit's built-ins and in other supporting code/libs). Better to be consistent across them all.
Changes in future - Finally, there may be a difference in a future implementation.
*Technical* - Its the expected value's equals method that is used:
There's one subtle difference after looking at the code. Many of the uses of assertEquals() will end up running through this method:
115 static public void assertEquals(String message, Object expected,
116 Object actual) {
117 if (expected == null && actual == null)
118 return;
119 if (expected != null && isEquals(expected, actual))
120 return;
...
128
129 private static boolean isEquals(Object expected, Object actual) {
130 return expected.equals(actual);
131 }
Its the equals method of the expected value that is used when both objects are non-null. One could argue that you know the class of the expected value (and thus know the behavior of the equals method of the expected value's class) but you may not necessarily know for certain the class of the actual value (which in theory could have a more permissive equals method). Therefore, you could get a different result if you swap the two arguments (i.e. the two different classes' equals methods are not reflexive of each other):
A contrived case would be an expected value of an ArrayList and an actual value that could return any type of Collection instance, possibly an ArrayList, but also possibly an instance of a custom Collection non-List class 'Foo' (i.e. Foo does not implement List). The ArrayList's equals method (actually its AbstractList.equals) specifies:
Returns true if and only if the specified object is also a list, both
lists have the same size, and all corresponding pairs of elements in
the two lists are equal.
Perhaps 'Foo' class's equals method is more permissive specifying:
Returns true if and only if the specified object is also a collection, both
collections have the same size, and both collections contain equal objects
but not necessarily in the same order.
By saying:
ArrayList expectArrayList = ...;
Collection actualCollectionPossiblyFoo = ...
Assert.assertEquals(expectedArrayList, actualCollectionPossiblyFoo)
you are saying you expect something equivalent to an ArrayList (according to ArrayList/AbstractList's definition of equals). This will fail if
actualCollectionPossiblyFoo is really of class Foo and thus not a List as
required by the ArrayList equals method.
However, this isn't the same as saying:
ArrayList expectedArrayList = ...;
Collection actualCollectionPossiblyFoo = ...;
Assert.assertEquals(actualCollectionPossiblyFoo, expectedArrayList);
because actualCollectionPossbilyFoo may be an instance of Foo and
Foo may consider itself and expectedArrayList to be equal according to
Foo class's equals method.
There is no specific reason. They could have ordered their parameters the other way. BTW, TestNG does it the other way.
For better readability and expressibility, I prefer using fluent assertions with fest-assert