JUnit/Mockito - How to capture changes in an argument's field? - java

I have an ObservableBoolean which is a pretty simple data container wrapping a primitive boolean. I want to use JUnit/Mockito to verify that the primitive boolean's value changes to true followed by false. I am setting up a mock OnPropertyChangedCallback like so:
Observable.OnPropertyChangedCallback loadingCallback = mock(Observable.OnPropertyChangedCallback.class);
viewModel.loading.addOnPropertyChangedCallback(loadingCallback);
I am then running the code under test which does:
loading.set(true);
loading.set(false);
Each of these calls fires the onPropertyChanged method on the loadingCallback, passing the same ObservableBoolean instance as an argument.
I've tried using an ArgumentCaptor and a custom ArgumentMatcher. Both methods successfully show that the onPropertyChange method has been called twice, however, neither of them maintain a history of what happened to the primitive boolean within the ObservableBoolean. Instead, I can only see the most recent value set on it, which is false.
How can I maintain a history of what happened to the primitive boolean within the ObservableBoolean? Again, I simply need to verify that it was set to true followed by false.

You could create a stub which implements Observable.OnPropertyChangedCallback and records the invocations and then provides a public accessor to these recorded invocations. Your test would then use the public accessor to these recorded invocations when asserting.
For example:
OnPropertyChangedCallbackStub loadingCallback = new OnPropertyChangedCallbackStub();
viewModel.loading.addOnPropertyChangedCallback(loadingCallback);
// invoke the code-under-test which, internally, invokes ...
// loading.set(true);
// loading.set(false);
assertTrue(2, loadingCallback.recordedInvocations().size());
assertTrue(loadingCallback.recordedInvocations().contains(true));
assertTrue(loadingCallback.recordedInvocations().contains(false));

I'm posting the implementation of the class #glytching suggested in his answer:
val callback = BooleanObservableCallback()
viewModel.isLoading.addOnPropertyChangedCallback(callback)
viewModel.onLoginButtonClicked()
assertThat(callback.recordedInvocations, hasSize(2))
assertThat(callback.recordedInvocations[0], `is`(true))
assertThat(callback.recordedInvocations[1], `is`(false))
class BooleanObservableCallback : Observable.OnPropertyChangedCallback() {
private val _recordedInvocations = mutableListOf<Boolean>()
val recordedInvocations: List<Boolean>
get() = _recordedInvocations.toList()
override fun onPropertyChanged(sender: Observable?, propertyId: Int) {
if (sender is ObservableBoolean) {
_recordedInvocations.add(sender.get())
}
}
}

Related

Java reflection: automatically invoke the right overloaded method based on parameters and signature

Say have an overloaded method called doTask:
public class Game {
void doTask(Joker joker);
void doTask(Batman batman, Robin robin);
}
I would like to invoke the right method, given the name of the method ("doTask") and an array of parameters whose number and types are not known a priori.
Normally, this involves three steps at least:
1. Find the number of the parameters and their types, and make an array Class[] myTypes.
2. Identify the correct overloaded Method, i.e. Method rightMethod = game.getClass().getMethod("doTask", myTypes);
3. Invoke the method: rightMethod.invoke(paramArray).
Does there exist a facility to ask Java reflection to automatically identify the right overloaded method to use, and save us from having to do Steps 1 and 2? I'm thinking ideally, this would be like:
Library.invoke("doTask", paramArray);
There is such a facility, java.beans.Statement, resp. Expression if a return value is needed:
Game game = new Game();
Joker joker = new Joker();
Statement st = new Statement(game, "doTask", new Object[]{ joker });
st.execute();
However, it only works for public methods.
Also, unlike java.lang.reflect.Method, this facility has not been adapted to support varargs parameters, so you have to create a parameter array manually.
It can be demonstrated, that it does the work of selecting the right target method based on the argument types, which are not necessarily identical to the parameter types:
ExecutorService es = Executors.newSingleThreadExecutor();
class Foo implements Callable<String> {
public String call() throws Exception {
return "success";
}
}
// has to choose between submit(Callable) and submit(Runnable)
// given a Foo instance
Expression ex = new Expression(es, "submit", new Object[]{ new Foo() });
Future<?> f = (Future<?>)ex.getValue();
System.out.println(f.get());
es.shutdown();
First - to answer your question - no, there is no such facility.
Second, step 2 is a bit more complicated as it doesn't suffice to create a class array from the parameters and call getMethod.
Actually you have to iterate over all methods, that match the name, number of arguments and compare the argument types of the method for assignment compatibility for the given argument types (i.e. methodArgType.isAssignableFrom(paramType)), to ensure that compatible subtypes of the method arguments types are correctly reflected. Things get slightly more complicated with varargs.

Why would one use a `java.util.function.supplier`, when one can just call a method?

I saw some example of of using supplier interface at https://dzone.com/articles/supplier-interface.
My question is, if in the above example I could do something as easy as :
driveVehicle(new Vehicle());
driveVehicle(new Car());
Why would one want to use supplier interface, if all it does is call a method, without taking in any parameters.
Suppose you have parameters stored in database that you want to keep in constant all over your app
// Assume retrieveSystemParameter query database which allows to change parameters
public static String SYSTEM_PARAMETER = StaticUtilities.retrieveSystemParameter();
That value will be initialized once and won't change untill a redeployment. That being said, if instead you use a supplier :
public static Supplier<String> SYSTEM_PARAMETER_SUPPLIER = StaticUtilities::retrieveSystemParameter;
When you need the value somewhere you will call SYSTEM_PARAMETER_SUPPLIER.get() which will retrieve parameter in the database when needed - that way if you change a parameter in database, you won't have to redeploy.
As you can see, Suppliers are lazy. They do the work when you ask them to work (by calling .get()) - that may allow you some performance gain if you deal with them wisely. Sometimes you will call a method which expect a variable X passing in method retrieveX and then end up not needing X in the method because some conditions were not met. In that case you will lose performance as you will execute the code to retrieve X while a supplier that retrieve X would only execute it when calling .get and you would only do that call if the conditions were met.
Disclaimer : the system parameter constant is just the first example that came to my mind, but considering it query the database on each .get() you'd rather cache the parameter and have the cache call .get() at a specific interval.
I guess Optional might be perfect example. Consider the following snippet:
final Product firstProduct = Optional.ofNullable(product)
.orElse(productDao.findProductById(id));
final Product secondProduct = Optional.ofNullable(product)
.orElseGet(() -> productDao.findProductById(id));
You're getting a product that may be null. In order to determine firstProduct java will have to call expression in orElse method so no matter product is null or not you always have to determine value that will be returned in case product is null.
In order to determine secondProduct database doesn't have to be queried in case product is not null because you're passing a Supplier that will be called only if product is null.
Another example is when your method that accepts a supplier is not pure (i.e., it has side effect), and the side effect happens before calling the lambda, and the behaviour of the lambda is affected by the side effect.
Consider, for instance, this example:
public class TestClass {
private String field;
public String getField() {
return field;
}
public void method(Supplier<String> supplier) {
field = "This is";
System.out.println(supplier.get() + " a test");
}
public static void main(String[] args) {
TestClass c = new TestClass();
c.method(() -> c.getField());
}
}
Here, method() is not pure, as it changes the value of field, which is used later in the lambda (through calling the getField() method). As the lambda is called in place (i.e., when get() is called), calling getField() will happen after setting the field. In other words, method() accepts a Supplier<String> instead of a String in an attempt to let the clients safely call the getField() method.
Of course, having side effects should be avoided wherever possible, and this is just a toy example, but it shows a potential place where a supplier can be used.
Supplier adds one more level of indirection.
Given that "All problems in computer science can be solved by another level of indirection", it's likely that there are some problems that can be solved by using a Supplier.
Beware, however, of the corollary "...except for the problem of too many layers of indirection."
So, if there's no problem to solve, then Supplier is overkill and you should stick to directly invoking new.
Put differently: mistrust any "pattern" or "best practice" that doesn't start by explaining a problem (your question shows, you actually do mistrust, so just keep on asking this kind of questions).
I use it to avoid the unnecessary creation of additional states:
private Supplier<Boolean> detach = () -> false;
private Supplier<Boolean> isAttached = () -> false;
private Supplier<Integer> index = () -> null;
private final Function<List<ObserverWrapper<X, Y>>, Boolean> attachFun = observers -> {
isAttached = () -> observers.contains(this);
detach = () -> observers.remove(this);
index = () -> observers.indexOf(this);
return observers.add(this);
};
public boolean attach(List<ObserverWrapper<X, Y>> observers) {
return attachFun.apply(observers);
}
public boolean isAttached() {
return isAttached.get();
}
public Integer observerIndex() {
return index.get();
}
Which some would say is unnecessary in itself, but then it becomes a philosophical problem.
A problem which would not exist if computers didn't exist, and then it becomes a real world problem of indirection.
I may admit that suppliers for me may have become an addiction, but in my mind they feel like the natural extrapolation and extension of all the programming axioms and principles.
You could use a Supplier in a map based factory class
public class StackService {
final static String INTEGERS = "Integers";
final static String DOUBLES = "Doubles";
final static String STRINGS = "Strings";
final static Map<String, Supplier<Stack>> stackType;
static {
stackType = new HashMap<>();
stackType.put(INTEGERS, Stack<Integer>::new);
stackType.put(DOUBLES, Stack<Double>::new);
stackType.put(STRINGS, Stack<String>::new);
}
public Stack<?> createStackOfType(String stackType) {
return stackType.get(stackType).get();
}
}
Here if you were to just use new Stack() you would be returning a reference to the same object rather than a new one.

Passing and setting booleans - Java/Android

I have a class like so:
public class Achievements(){
boolean score100_Earned_Offline;
boolean score1000_Earned_Offline;
final String score100 = "xxxxxxxxxx" //where xxxxxxxxxx would be replaced with the achievement's Google Play Games ID
final String score1000 = "xxxxxxxxxx" //where xxxxxxxxxx would be replaced with the achievement's Google Play Games ID
}
In my Game class, I check the state of the achievements every tick and act on them as necessary like so (assume all methods to be valid and defined - this is cut down to provide the code necessary to the question).......
public class Game(){
public void checkAchievements(Achievements achievements){
if (score>=100){
unlockAchievement(achievements.score100, achievements.score100_Earned_Offline);
}
if (score>1000){
unlockAchievement(achievements.score100, achievements.score1000_Earned_Offline);
}
}
public void unlockAchievement(String achievementToUnlock, boolean thisAchievementOfflineFlag){
//If user is signed in, then we are ready to go, so go ahead and unlock the relevant achievement....
if (checkSignedIn()){
Games.Achievements.unlock(getApiClient(), achievementToUnlock);
//Otherwise, I want to do is set the relevant flag to true so it can be checked when the user does eventually log in
else{
thisAchievementOfflineFlag=true;
}
}
}
Pass by value
In the 'unlockAchievement' method, the boolean 'thisAchievementOfflineFlag' does get set to true if the user is not logged in, however, it doesn't effect the actual boolean that was originally sent into the method (which as you can see is defined in my 'Achievements' class). I'm guessing this is because Java is Pass by Value and is therefore, creating a local copy of the variable which is valid inside the method only. I did try using Boolean too (wrapper class) but got the same results.
Other ways to achieve this?
I've currently got it set up so I can define each achievement as an enum so each one will have it's own copy of the boolean flag. However, I'm aware that it's not recommended to use enums in Android so if there is a better way that I am missing, I would rather avoid them.
Please note that I don't want to use if checks or switch statements as this is taking place in a game-loop.
Any suggestions appreciated
This is all because Java's implementation of Boolean (also, for example String) is immutable for safety reasons. You can see it here: http://www.explain-java.com/is-string-mutable-in-java-why-wrapper-classes-immutable-in-java/
You can solve your problem by introducing an object wrapper for that boolean:
public class BooleanWrapper {
private boolean value;
public void set(boolean value) {
this.value = value;
}
public boolean get() {
return value;
}
}
Now, this object reference will be passed by value but will still point to the same BooleanWrapper object on the heap. You can simply use getters and setters to change the inner boolean value.
Then your code would become:
public void unlockAchievement(String achievementToUnlock, BooleanWrapper thisAchievementOfflineFlag){
if (checkSignedIn()){
Games.Achievements.unlock(getApiClient(), achievementToUnlock);
else {
thisAchievementOfflineFlag.set(true);
}
}
Java is pass-by-value:
When you pass boolean then you for sure passed it by value, while it is a primitive type. When you pass Boolean, you would think it's an object and that you can change it's state, but actually you cannot because Boolean is implemented as an immutable object (as already said). You can confirm this just by reading the code of java.lang.Boolean.
But if you create your own wrapper class, and in a sense, you control whether you implement it in immutable or mutable way. BooleanWrapper I wrote lets you change the state of that object. And when you pass an object such as this one to the method, it's passed by value. That means that another reference is created, but it points to the same object on heap (see image below).
You could use an AtomicBoolean, which will have pass-by-reference semantics.

Correct design pattern to change instance of data type at run time

I had been thinking of using a generic factory pattern for this, however I just want to make sure that I am using it correctly.
First of all, this has to be Java-based, due to client needs.
My application can instantiate several objects, and each of those objects should be able to change type at run time. For instance, a variable can start out as a float, be converted to an int, then to a char, then back to a float. That would be a basic example, however custom data types can be added in for extra fun.
Is a generic factory pattern the correct one to use in this case? Or, is there something better? To me, the factory pattern seems to be better at instantiating and not updating (unless if I essentially destroyed and re-instantiated the variable).
More detail:
This is an evolutionary algorithm where I don't necessarily know the types when the program starts. It may find that an int is more desirable than a float, based on how evolution goes.
For instance, if I start with a floating point value of 4.34:
// start of program
object var = 4.34;
// evolution running......
...
// evolution determines that var would be better as a float
var.convertToInt();
// var is now an int with a value of 4
My initial thought had been to have a generic factory type object where I keep track of the current 'type' of the object and return the appropriate value. So in the beginning it would return a float, and after the conversion would return the int-converted value (mapped to an internal int).
Edit 2: Code clarification.
I guess my point is just not coming through. Here is an example of what I would expect to see, code-wise.
object var = new object(int, 4); // create int variable with value of 4
// where object is whatever base design pattern i am using here
...
var.toFloat(); // convert var to float, value is now 4.0
System.out.println(var.getValue()); // prints 4.0
...
var.toCustomClass(); // var is now a custom datatype
System.out.println(var.getValue()); // calls the print method of the class
I should also mention that the instance of var needs to persist throughout execution, as it is an object within my evolutionary algorithm and can't be destroyed and re-instantiated as something else.
If you explain why you want to do this it might help. Your best bet based on what you have said so far will be just to always use the type as Number and then store whatever version you need. For example number.toInt, number.toDouble etc.
For more complex types define a common interface that they all implement and store them using that interface, then write appropriate mapping methods or use a library such as Dozer to do the mapping for you.
You are going to need to create your own class to handle this. For example:
public class Value {
Object value;
Object getValue();
void toInteger() {
if (value instanceof Number) {
value = Integer.valueOf(((Number)value).intValue());
} else {
// Handle the conversion however you handle it
}
}
}
Maybe this can help.
By providing a generic method, the return type is casted to the type of the variable to hold the result. A ClassCastException will be launched if the types are not compatible
public class Wrapper {
private Object src;
public Wrapper(Object o) {
src = o;
}
public String getType(){
return src.getClass().getName();
}
public <E> E getValue() {
return (E)src;
}
public void toInteger(){
//dummy implementation
if(src instanceof Double){
src=new Integer(String.valueOf((int)Math.floor((Double)src)));
}
}
public static void main(String args[]){
Wrapper wrapper=new Wrapper(new Double(4.8));
System.out.println(wrapper.getType());
Double myDouble=wrapper.getValue();
System.out.println(myDouble);
wrapper.toInteger();
System.out.println(wrapper.getType());
Integer myInteger=wrapper.getValue();
// Double exceptionInProgress = wrapper.getValue();
System.out.println(myInteger);
}
}

How to change the value of a boolean var inside a method?

This is maybe so silly.
I have a boolean variable inside the main method. By calling another method of this class or another class I want my boolean value to be modified in the main method. I do this but the change happens only in the called method(locally), not the caller(main). I think this is because of the pass-by-value feature of java.
I even tried Boolean type, but the same problem there!
Actually I'll use this to manage the ordering of concurrent threads. The main processor will check for the boolean value of every thread to see if it is ok to continue and tick the clock. After ticking the clock the main will make the vars false and will wait until the vars are again true. the sub-threads will start their task if the boolean value of them each is false. After the task is done they will make the vars to true so the main processor is able to tick again.
So I want something without a return. I mean as the value is changed inside the method the main could see it.
boolean var = true;
var = methodWhichReturnsTheNewValueOfTheVariable();
and inside the called method:
return newBooleanValue;
or
SomeObjectWithBooleanVariableInside var = new SomeObjectWithBooleanVariableInside(true);
methodWhichModifiesTheObject(var);
and inside the called method:
var.setBooleanValue(newBooleanValue);
A Boolean is such an object: it contains a boolean value. But it's intentionally designed as immutable: its wrapped boolean value can't be changed. So you need to create your own, functional object.
The usual way to do this is the following:
public static void main(String[] args) {
boolean myVar = true;
...
...
myVar = myFunction();
}
public static boolean myFunction() {
// the method should do it's calculation and return the value:
return false;
}
Yes - you cannot modify passed-by-value parameter inside a method in Java (for example in C# you would write method(ref param)).
Why can't you return this value using the method:
public boolean method(params...) {...}
Or you can pass in param the reference to caller:
public void method(params..., CallerClass caller) {
//do something
caller.setValue(Boolean.FALSE);
}
Or you can make this variable accessible in caller and calling method scopes - static variable, etc.
Primitive types are passed by value, so you can't change variables coming as parameter in a method.
This makes also easier to understand how a program works, since this kind of behavior is made more evident in an invocation like this:
boolean prime = false;
prime = isPrime(number);
you can see that found variable is reassigned; while you can assume that number will remain unchanged. This helps in code readability.
There is a dirty trick that sometime can be used. Since arrays are objects, you can use an array to wrap a primitive type:
boolean[] prime = { false };
isPrime(number, result);
public void isPrime(int number, boolean[] result) {
result[0] = true;
}
The object reference is passed by value too, but here we change the content of the array, not the array reference.
This works. But, I don't recommend to design your code like this.
Sometimes, knowing this trick can be useful in unit tests though.
when you think that you changed the value of the primitive boolean it only changed the value in the scope of that method. same with Boolean as it is immutable. changing its value actually assigned a new value to it inside the scope of that method.
you should return the new value from that method and then assign it or you could also use a global boolean that is known to all and to change that one.
(and by the way, if you're dealing with concurrency check out AtomicBoolean)

Categories