Testing an interface with Mockito verify - junit

I'm trying to test a class which has an interface with 3 argument method.
Method I'm testing is like this
formElementCallback.stateChanged(formElement1, FormElementState.DISABLED, "");
formElementCallback.stateChanged(formElement2, FormElementState.DISABLED, null);
and this is the test method
Mockito.verify(mockFormElementCallback, Mockito.atLeastOnce()).stateChanged(Mockito.argThat(new ArgumentMatcher<FormElement>() {
#Override
public boolean matches(Object argument) {
//matcher for formObject
FormElement formElement = (FormElement) argument;
return true;
}
}), Mockito.argThat(new ArgumentMatcher<FormElementState>() {
#Override
public boolean matches(Object argument) {
//matcher for state
return true;
}
}), Mockito.argThat(new ArgumentMatcher<Comparable>() {
#Override
public boolean matches(Object argument) {
//matcher for value
return true;
}
}));
Since the interface is called 2 times, Mockito.verify(object, Mockito.times(1) is not working. I tried to combine the logic with atLeastOnce() but then whenever I assert formElement1, formElement2 is called too so the test failed. And even if I use an if statement, matcher scope for value and state will not be aware of the form element scope.
Is there a way that I can assert like this?
If argument equals formElement1, Assert state DISABLED, Assert value ""
If argument equals formElement2, Assert state DISABLED, Assert value null
Else AssertTrue(false) since interface must not be called with other form elements.
Edit: Solution must not be to combine 3 arguments into one and put State and value in formElement class. This is due to prevent outside classes to access the formElement itself and change the state manually. There is another implementation like this: .stateChanged(FormElementType type, FormElementState state, Comparable value);

Can you assert like this?
verify(formElementCallback).stateChanged(
formElement1, FormElementState.DISABLED, "");
verify(formElementCallback).stateChanged(
formElement2, FormElementState.DISABLED, null);
verifyNoMoreInteractions(formElementCallback);
See the javadoc for verifyNoMoreInteractions. You can do the same with InOrder, if that matters.

Related

JUnit what asserts should I use

I would like to ask for a help and suggestions what is a correct approach in my case (probably its easy but I'm just starting with JUnit). Here is a part of my code
public boolean arrayListEmpty()
{
if(numericalSequence.isEmpty() == true)
return true;
else
return false;
}
This is a public method from model which I suppose i should test, it's just returning true if my numericalsequence is empty as you can see. I cant check it directly invoking numericalSequence.isEmpty (in controller where I need it) because it is private.
So obvious thing is to check
assertEquals(true, test.arrayListEmpty());
So my question is about suggestions what other asserts should I use/what cases should I predict which can come out. Should I in Test method fill numericalSequence with some values and assert it also? (for me its not necessary because any value inserted into sequence = not null but maybe it is not so easy)
First of all, welcome to Stack Overflow!
Looking at your question, it sounds like you're new to unit-testing (correct me if I'm wrong). So, I'll break my answers in to two sections; (1) answering your question, and (2) to give a general direction of how to write good tests and testable classes.
1. Answering your question
There are a couple more use cases you can think of here:
What happens if numericalSequence is null?
What if numericalSequence has 1 element?
What if numericalSequence has a null element?
Some of the cases above may not be possible depending on how your class is set up, but it's a test worth having so that any changes to the class that violates the "previously agreed behavior" of one of these test cases would fail.
2. Writing good tests
There are no strict guidelines on what to do in order to write good tests, however, if you structure your code to be testable, you'll find that writing good tests becomes easier, and would be less of chore. Allow me to explain.
NOTE: This is not a comprehensive guide, but is meant to start your journey in to the path of how to write better code, and better tests
So assume a class that needs to be tested is written like this:
class MyClass {
// NOTE: This is not `final`
private List<Integer> numericalSequence;
public MyClass() {
this.numericalSequence = new ArrayList<>();
}
public void doSomething(Integer x) {
if (x < 0) {
numericalSequence = new ArrayList<>();
} else {
numericalSequence.add(2 * x);
}
}
public boolean arrayListEmpty() {
// NOTE: Your sample code can be reduced to this one-liner
return numericalSequence.isEmpty();
}
}
Here are some of the flaws in the above code:
doSomething method allows nullable (boxed integer) values and so can cause NullPointerException in the first if statement.
The numericalSequence member is not final and hence the code that sets it to null is valid inside the doSomething method
The arrayListIsEmpty method does not check if numericalSequence is null
If I want to test how arrayListIsEmpty behaves when numericalSequence is null, or has null elements, it is hard to do so, unless you know how to get the class to that state.
If the class was re-written to the following:
class MyClass {
private final List<Integer> numericalSequence;
public MyClass() {
this(new ArrayList<>());
}
// Should be made public only if the classes that use this one needs to
// initialize this instance with the sequence. Make this package-private
// otherwise.
public MyClass(List<Integer> sequence) {
this.numericalSequence = sequence;
}
public void doSomething(int x) {
if (x < 0) {
// COMPILE ERROR: Cannot assign to a final member
// numericalSequence = new ArrayList<>();
numericalSequence.clear();
} else {
numericalSequence.add(2 * x);
}
}
public boolean arrayListEmpty() {
return numericalSequence == null || numericalSequence.isEmpty();
}
}
A few things to note about the above structure:
There are two constructors; the default invokes the one that takes a list of integers as the sequence, so that it reuses any logic that both would need to share. There are no logic in this example, but hopefully you'll come across one soon.
The doSomething() method doesn't accept Integer value, but int value that makes sure that x is never null (Java numerical primitive types cannot be null). This also means, numericalSequence cannot contain null values through doSomething().
Since numericalSequence can be initialized from outside of this class, the arrayListEmpty() method makes sure to check that numericalSequence is either null is truly empty.
Now you can write test cases like so:
#Test
public void arrayListEmpty_WhenListIsNull() {
MyClass test = MyClass(null);
assertTrue(test.arrayListEmpty());
}
#Test
public void arrayListEmpty_WhenListIsEmpty() {
MyClass test = MyClass();
assertTrue(test.arrayListEmpty());
}
#Test
public void arrayListEmpty_WhenListHasOnlyOneNonNullElement() {
List<Integer> sequence = new ArrayList<>();
sequence.add(0);
MyClass test = new MyClass(sequence);
assertFalse(test.arrayListEmpty());
}
#Test
public void arrayListEmpty_WhenListHasOnlyOneNullElement() {
List<Integer> sequence = new ArrayList<>();
sequence.add(null);
MyClass test = new MyClass(sequence);
assertFalse(test.arrayListEmpty());
}
Since doSomething() adds/clears the sequence, when writing tests for doSomething() make sure the call and verify the state of the class by checking the return value of arrayListEmpty().
For example:
#Test
public void doSomething_WhenInputLessThanZero() {
List<Integer> sequence = new ArrayList<>();
sequence.add(0);
MyClass test = new MyClass(sequence);
test.doSomething(-1);
assertTrue(test.arrayListEmpty());
}
My intention was to show a couple of things:
Structure your tests cases to be small and concise
Design your class to be easily testable
Hope this helps.

<f:selectItems> returns a validation error [duplicate]

I have a problem with a p:selectOneMenu, no matter what I do I cannot get JSF to call the setter on the JPA entity. JSF validation fails with this message:
form:location: Validation Error: Value is not valid
I have this working on several other class of the same type (ie, join table classes) but cannot for the life of me get this one working.
If anyone can throw some troubleshooting/debugging tips for this sort of problem it would be greatly appreciated.
Using log statements I have verified the following:
The Conveter is returning correct, non null values.
I have no Bean Validation in my JPA entities.
The setter setLocation(Location location) is never called.
This is the simplest example I can do and it simply will not work:
<h:body>
<h:form id="form">
<p:messages id="messages" autoUpdate="true" />
<p:selectOneMenu id="location" value="#{locationStockList.selected.location}" converter="locationConverter">
<p:ajax event="change" update=":form:lblLocation"/>
<f:selectItems value="#{locationStockList.locationSelection}"/>
</p:selectOneMenu>
</h:form>
</h:body>
Converter:
#FacesConverter(forClass=Location.class, value="locationConverter")
public class LocationConverter implements Converter, Serializable {
private static final Logger logger = Logger.getLogger(LocationConverter.class.getName());
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
if (value.isEmpty())
return null;
try {
Long id = Long.parseLong(value);
Location location = ((LocationManagedBean) context.getApplication().getELResolver().getValue(context.getELContext(), null, "location")).find(id);
logger.log(Level.SEVERE, "Converted {0} to {1}" , new Object[] {value, location});
return location;
} catch (NumberFormatException e) {
return new Location();
}
}
#Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
if (value == null || value.toString().isEmpty() || !(value instanceof Location))
return "";
return String.valueOf(((Location) value).getId());
}
}
Console output:
// Getter method
INFO: Current value=ejb.locations.Location[id=null, name=null, latitude=0.0, longitude=0.0]
// Session Bean
INFO: Finding ejb.locations.Location with id=3
// Session Bean
INFO: ### Returning : ejb.locations.Location[id=3, name=mdmd, latitude=4.5, longitude=2.3]
// Converter
SEVERE: Converted 3 to ejb.locations.Location[id=3, name=mdmd, latitude=4.5, longitude=2.3]
// Getter method -> Where did my selected Location go ??
INFO: Current value=ejb.locations.Location[id=null, name=null, latitude=0.0, longitude=0.0]
Validation fails with the message "form:location: Validation Error: Value is not valid"
This error boils down to that the selected item does not match any of the available select item values specified by any nested <f:selectItem(s)> tag during processing of the form submit request.
As part of safeguard against tampered/hacked requests, JSF will reiterate over all available select item values and test if selectedItem.equals(availableItem) returns true for at least one available item value. If no one item value matches, then you'll get exactly this validation error.
This process is under the covers basically as below, whereby bean.getAvailableItems() fictionally represents the entire list of available select items as defined by <f:selectItem(s)>:
String submittedValue = request.getParameter(component.getClientId());
Converter converter = component.getConverter();
Object selectedItem = (converter != null) ? converter.getAsObject(context, component, submittedValue) : submittedValue;
boolean valid = false;
for (Object availableItem : bean.getAvailableItems()) {
if (selectedItem.equals(availableItem)) {
valid = true;
break;
}
}
if (!valid) {
throw new ValidatorException("Validation Error: Value is not valid");
}
So, based on the above logic, this problem can logically have at least the following causes:
The selected item is missing in the list of available items.
The equals() method of the class representing the selected item is missing or broken.
If a custom Converter is involved, then it has returned the wrong object in getAsObject(). Perhaps it's even null.
To solve it:
Ensure that exactly the same list is been preserved during the subsequent request, particularly in case of multiple cascading menus. Making the bean #ViewScoped instead of #RequestScoped should fix it in most cases. Also make sure that you don't perform the business logic in the getter method of <f:selectItem(s)>, but instead in #PostConstruct or an action event (listener) method. If you're relying on specific request parameters, then you'd need to explicitly store them in the #ViewScoped bean, or to re-pass them on subsequent requests by e.g. <f:param>. See also How to choose the right bean scope?
Ensure that the equals() method is implemented right. This is already done right on standard Java types such as java.lang.String, java.lang.Number, etc, but not necessarily on custom objects/beans/entites. See also Right way to implement equals contract. In case you're already using String, make sure that the request character encoding is configured right. If it contains special characters and JSF is configured to render the output as UTF-8 but interpret the input as e.g. ISO-8859-1, then it will fail. See also a.o. Unicode input retrieved via PrimeFaces input components become corrupted.
Debug/log the actions of your custom Converter and fix it accordingly. For guidelines, see also Conversion Error setting value for 'null Converter' In case you're using java.util.Date as available items with <f:convertDateTime>, make sure that you don't forget the full time part in the pattern. See also "Validation Error: Value is not valid" error from f:datetimeConverter.
See also:
Our selectOneMenu wiki page
How to populate options of h:selectOneMenu from database?
Make multiple dependent / cascading selectOneMenu dropdown lists in JSF
If anyone can throw some troubleshooting/debugging tips for this sort of problem it would be greatly appreciated.
Just ask a clear and concrete question here. Do not ask too broad questions ;)
In my case I forgot to implement a correct get/set methods. It happened because I have changed a lot of attributes along the development.
Without a proper get method, JSF canĀ“t recover your selected item, and happens what BalusC said at item 1 of his answer:
1 . The selected item is missing in the list of available items. This can happen if the list of available items is served by a request scoped bean which is not properly reinitialized on subsequent request, or is incorrectly doing the business job inside a getter method which causes it to return a different list in some way.
This can be a Converter Issue or else DTO issue.
Try to solve this, by adding hashCode() and equals() methods in your object DTO; In the above scenario you can generate these methods within the Location object class which indicate as the 'DTO' here.
Example:
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (id ^ (id >>> 32));
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Location other = (Location) obj;
if (id != other.id)
return false;
return true;
}
Please note that the above example is for an 'id' of type 'long'.

JUnit: should I do null-checks after assertNotNull

Should I do null-checks after assertNotNull to avoid null-pointers in test code? E.g.
assertNotNull(foo);
if (foo != null) {
assertNotNull(foo.getBar());
}
Or just
assertNotNull(foo);
assertNotNull(foo.getBar());
You are doing right with...
assertNotNull(foo);
assertNotNull(foo.getBar());
You don't need to set another condition to check the same if you previously did it.
Using assertX methods ensure the condition is actually asserted. So, by using assertNotNull you ensure that something is not null.
The correct way is as you showed:
assertNotNull(foo);
assertNotNull(foo.getBar());
If you start digging deeper into the assertNotNull method, you will see this calls:
// First call
static public void assertNotNull(Object object) {
assertNotNull(null, object);
}
// Second call
static public void assertNotNull(String message, Object object) {
assertTrue(message, object != null);
}
// Third call
static public void assertTrue(String message, boolean condition) {
if (!condition) {
fail(message);
}
}
Quoting the assertTrue documentation:
Asserts that a condition is true. If it isn't it throws an AssertionError with the given message.
Conclusion, you don't have to do null checks after asserting for not null values since junit is taking care of that for you
You even don't need to have the first null check. The test will fail with a NullPointerException if foo is null. It is a matter of taste whether to have the null check or not.

mockito -using one of the values from list of values to compare in matcher

My method interface is
Boolean isAuthenticated(String User)
I want to compare from list of values if any of the users are passed in the function from the list, then it should return true.
when(authService.isAuthenticated(or(eq("amol84"),eq("arpan"),eq("juhi")))).thenReturn(true);
I am using additional argument matcher 'or' but above code is not working. How can I resolve this issue?
or does not have a three-argument overload. (See docs.) If your code compiles, you may be importing a different or method than org.mockito.AdditionalMatchers.or.
or(or(eq("amol84"),eq("arpan")),eq("juhi")) should work.
You might also try the isOneOf Hamcrest matcher, accessed through the argThat Mockito matcher:
when(authService.isAuthenticated(argThat(isOneOf("amol84", "arpan", "juhi"))))
.thenReturn(true);
You could define separate answers:
when(authService.isAuthenticated(eq("amol84"))).thenReturn(true);
when(authService.isAuthenticated(eq("arpan"))).thenReturn(true);
when(authService.isAuthenticated(eq("juhi"))).thenReturn(true);
If you're not interested in pulling in a library, you can iterate over all of the values you want to add to the mock:
// some collection of values
List<String> values = Arrays.asList("a", "b", "c");
// iterate the values
for (String value : values) {
// mock each value individually
when(authService.isAuthenticated(eq(value))).thenReturn(true)
}
For me this works:
public class MockitoTest {
Mocked mocked = Mockito.mock(Mocked.class);
#Test
public void test() {
Mockito.when(mocked.doit(AdditionalMatchers.or(eq("1"), eq("2")))).thenReturn(true);
Assert.assertTrue(mocked.doit("1"));
Assert.assertTrue(mocked.doit("2"));
Assert.assertFalse(mocked.doit("3"));
}
}
interface Mocked {
boolean doit(String a);
}
Check if you're setting up mockito correctly, or if you're using the same Matchers as I do.

How to define the return type of AS3 method that may return or not return a result?

public function t()
{
if(xxx)return xxx;
//don't return anything
}
How to define the return type for such method?
A function either has to return nothing, or return something - it can't do both. The reason being, what if you write this code:
var someValue = someFunction();
How would this code be handled if sometimes someFunction returned a value, and sometimes it didn't?
Your problem is a really common one, though, and there are several ways to work around it.
Sentinel Values
You can return special-case values that you treat as non-values (such as null, NaN, "", or -1). These special-case values are called sentinel values. The users of your function (maybe your own code) would check the result after calling it. If it gets one of the sentinel values back, it doesn't use the result.
Try-style Functions
You could also use a pattern commonly used in C#/.Net that they call "Try-methods", but you can call "Try-functions". Actionscript doesn't work exactly like C#, but we can get close enough for this pattern to work.
To do this, return Boolean, returning true if you have a value, and false if you don't. Then give your function an Object parameter, and populate a property with the actual return value:
function trySomeFunction(result:Object) : Boolean
{
if(xxx)
{
result.Value = xxx;
return true;
}
return false;
}
// ...
var result:Object = { Value:null };
if(trySomeFunction(result))
{
// Do something with the value here
}
Exceptions
If your method failed to do what it promised to do, you can throw an exception. Then you don't have to worry about what gets returned, because your code just dies.
Exceptions are great because people who call your code don't have to learn as much. They don't have to know that your function only succeeded if it doesn't return some magic value that is different for every function, they don't need to check if your function returns true/false, and they don't need to know that some property gets populated on an object when the function succeeded.
Without exceptions, if they forget to check for your special value, or the result of a "Try-function", an error might happen further on in the program. Or it might not happen at all, and the program will continue running, but be broken. In these cases, it is much harder to track down the problem.
With exceptions, your code just blows up the second it detects a problem, and gives you the line of code where your program realized it couldn't work correctly.
If it is normal and okay for your function to fail, though, you probably shouldn't throw an exception. You should probably use a "Try-function" or a sentinel value instead.
Everything that Merlyn says is fine, though perhaps a bit of overkill. If your method needs the potential to return null, then just pass xxx back whether it's null or not...
public function t():MyReturnType
{
return xxx;
}
... since you're going to have to do check the special condition in the calling method anyway:
public function caller():void
{
var value:MyReturnType = t();
if (value)
doSomethingPositive();
else
copeWithNullState();
}
Some people think that this is wrong and advocate creating a special 'null value' object in your return class, like this:
public class MyReturnType
{
public static const NULL:MyReturnType = new MyReturnType(null);
public function MyReturnType(identifier:String)
...
}
then in your function either return an interesting MyReturnType or NULL:
public function t():MyReturnType
{
return xxx || MyReturnType.NULL;
}
but then you've not really improved your caller method so why bother?
public function caller():void
{
var value:MyReturnType = t();
if (value != MyReturnType.NULL)
doSomethingPositive();
else
copeWithNullState();
}
Whatever you choose to do, eventually you're just going to have to test for special cases in the caller method. Personally I'd say it's better to keep it as simple as possible, and the special 'null value' in your class is over-complication.
I write plenty of functions that might return an object reference, but may also return null, like this:
public function findThingById( id:int ):MyThingType
{
... code here to search for/load/lookup thing with matching id
if (found)
{
return thing;
}
return null;
}
Wherever you call a function that might return null, you would either test the return value for null explicitly, or if you expect null just don't do anything with the return value. For built-in data types, you would use a special value rather than null (like NaN for Numbers illustrated above), but the principle is the same.
public function t():type
{
if(xxx)return xxx;
//don't return anything
}
so something like:
private function derp():void{
}
private function derp2():int{
}
private function derp3():Boolean{
}
etc
its always good practice to define the return type, and return an indicator variable if false (i.e return -1 for number), but if its really necessary you can do this:
public function t()
{
if(xxx)return xxx;
//don't return anything
}
don't specify a return type at all, and either it will return xxx or undefined, but I highly encourage using a return type.
But since flash runs on virtual memory it can basically adapt to your return type so it makes it a little flexible so you can return what ever.
EDIT:
public function t()
{
if(true){
return xxx; //xxx can by of any type
}
return NaN
}
EDIT:
so lets say you want the condition with a return type of int you would have
public function t():int
{
if(true){
return xxx; //where xxx != -1
}
return -1
}
this when we get back any number other then negative 1 we know the condition was true, but if we get -1 the condition was false. But if you numbers are any real numbers, use NaN keyword:
public function t():Number
{
if(true){
return xxx; //where xxx != -1
}
return NaN
}
this way if you get NaN back it means your condition was false
I should also mention that when your dealing with NaN use the isNaN() to determine if the return type was NaN or not:
example:
if(isNaN(t()) == true){
//if condition in function t() was false;
}
There is no way a single function can return void as well as returning a type. This is because void is not part of any inheritance chain, it is a top level concept meaning something very specific; it doesn't return anything.
Don't get confused between null and void, undefined and void, NaN and void. They are different concepts.
The answer to your question is simply that it can't, nor should it be done. When you hit a problem like this, it's good practice to step back and ask 'why' do you need to do this.
I would highly encourage that you mark this question as closed, and instead posted a higher level problem. For example,
How would I structure a class that has a variable xxx that does this and that and will be eventually set to a number when the user clicks. But if the user never clicks, it will be unset.... ecetera ecetera....
If you are 100% convinced you should do something like you're asking, you could 'fake' it by
function f():* {
var xxx:Number = 999;
if(xxx) {
return xxx;
} else {
return undefined;
}
}
var xx:* = f();
trace(xx);
But remember, from that point onwards you will need to check everytime xx is used to see if it undefined. Otherwise it will lead to errors.